跟踪类的所有对象


9

我是面向对象编程的新手,并且一直遇到这个问题。(我正在用Java编程)我一直不太愿意问这个问题,因为它看起来像是一个基本问题,但是我找不到关于它的任何信息,也没有关于它的问题,而且都没有我读过的教科书(在相当基本的水平上)已经涉及到这个问题:

我经常需要跟踪已创建的类的所有对象,以出于各种目的遍历它们。我目前编写程序的方式是这样的,许多对象仅从其他对象中引用,这意味着我没有数组或集合来引用它们。

我认为,由于这似乎是OOP中非常基本的必要,因此应该有一种相当制度化且简单的方法来解决此问题吗?保留一个类的所有对象的单独列表是通常的做法吗?

我想到了一个静态数组或集合,通过其构造函数,将添加创建的每个新对象。但是,这将不适用于子类,因为构造函数没有继承吗?

我意识到这个问题可能没有一个简单的答案。我只是希望有人能启发我一些关于这个问题的知识。我感觉好像我在这里缺乏核心知识。


5
跟踪者和跟踪者的更具体示例可能会有所帮助。根据上下文,使用方式等,可以通过许多不同的方式来处理此问题。
JustinC

2
我认为您可能从错误的角度来解决问题。一个给定类的所有实例的列表并不是很常见,拥有一个实例会引起各种各样的设计问题(因为现在即使在完全不相关的上下文中创建的实例也通过该列表相互依赖)。
tdammers

1
“出于各种目的通过它们迭代”…………?通常,一个对象具有一个“所有者”(不是一个正式的术语,更多的是关于程序语义的声明),并且该对象不具有任何其他目的。
AakashM 2013年

Answers:


8

我不知道为什么您需要保留一个类的所有实例的列表。

这将导致内存泄漏,因为这些对象将永远不会被丢弃,因为列表将在没有其他类之后引用它们。

但是,如果您真的想遵循该路线:

  1. 使用工厂模式。工厂类,带有实例化该类并返回对象的方法。这样,您就有了一个集中点来控制实例化。
  2. 使用Singleton模式来保存一个或多个保存实例的列表。
  3. 创建工厂后,使工厂将某种类型的每个对象放入列表中。

顺便说一句:构造函数是继承的。


当然,您可以给工厂一个“ dispose”方法,该方法将从实例的跟踪实例列表中删除该实例。但是没有办法明确调用它。或为实例提供一个在其工厂中触发dispose方法的dispose方法,该方法具有相同的缺点,但由于它离用户更近,更可见,因此实际上更有可能被调用。
jwenting

@jwenting当然是这样。但这会在类和工厂之间创建难看的不必要的依赖关系。类对创建它们的工厂一无所知。
TulainsCórdova2013年

因此,让工厂跟踪其创建的内容,而不是让对象告诉工厂对其进行注册...
jwenting

从技术上讲,一个单例将容纳我猜到的所有实例。一个实例。
钻机

3

应当注意,弱引用可以与其他给定解决方案结合使用,以使垃圾回收器在不再在其他地方引用跟踪的对象时处理它们。这样就消除了内存泄漏,而无需其他地方的代码来手动处理对象,也不必担心被跟踪。您可以提供ReferenceQueue来接收对已释放对象的引用的通知。

我想到了一个静态数组或集合,通过其构造函数,将添加创建的每个新对象。但是,这将不适用于子类,因为构造函数没有继承吗?

基类的构造函数在派生类的构造函数之前被调用。每个类至少有一个构造函数,并且构造函数不能被覆盖。


2

在制作游戏时,人们有时会希望对每种类型的游戏对象进行“自我管理”。

一种实现如下所示:

public class Car {

    static ArrayList<Car> list = new ArrayList<Car>();

    public Car() {
        list.add(this);
    }

    void kill() {
        list.remove(this);
    }

    static public void updateAll()
    {
        for (int i = list.size() - 1; i >= 0; i--)
        {
                list.get(i).update();
        }
    }

    public void update()
    {
        //update logic
    }
}

这样,可以将操作集合的方法声明为静态,而将非静态方法操作为实例(updateAll与update)。

虽然非常适合非常简单的场景,但即使是中等复杂度,通常也最好创建单独的管理器类。


1
您可以直接static ArrayList<ListeStatic> list = new ArrayList<ListeStatic>();在statc {..}中写一个ansress
cl-r

2
在Java方法中,名称以小写字母开头:uptdateAll(){..;}
cl-r

哎呀...它已经有一段时间,因为我已经播出我的Java公共
凯利托马斯

@KellyThomas一辆汽车将自己添加到列表中,他们将其从列表中删除。听起来不自然。
TulainsCórdova2013年

1
@CayetanoGonçalves作为静态字段,是所有实例共享的一个列表。
凯利·托马斯

2

尝试考虑上下文。创建对象时,是在特定上下文中进行的。例如,如果您的游戏是关于射击外星人的,那么您的应用将一直在创建新的外星人对象。它们将显示在一个名为Space的字段中(该字段可能是代表主UI的类)。

对于Space来说,拥有一个名为currentAliens的属性是很自然的,该属性将是一个数组,您将在其中添加每个创建的新外星人。如果要允许用户撕裂时空结构并立即销毁所有外星人,则需要遍历该集合并销毁每个对象。

如果您想从应用程序的其他部分访问此外星人集合(例如,从“设置”页面,您可能希望允许用户一口气消灭某些类型的外星人),则设置上下文将需要被授予访问Space对象的权限。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.