一个对象可以保存一组它自己的对象。但这如何与继承一起工作?

时间:2020-12-27 12:18:20

标签: java arrays class oop generics

我有以下抽象类:

public abstract class Entity{
  private final ArrayList<Entity> parent;

  // a lot of code that is not important now
}

这个类的一个实例拥有一个“它自己的对象”的 ArrayList。但是如何为“实体”的所有子类实现相同的目标?例如。我有这门课:

public class Player extends Entity {
   // a lot of code that is not important now
}

现在“玩家”持有一个 ArrayList<Entity>,但它应该持有一个 ArrayList<Player>。这对于 Entity 的所有子类应该是相同的(有很多)。我的伪代码是:ArrayList<THIS> parent

我怎样才能做到这一点?

4 个答案:

答案 0 :(得分:4)

在实践中,你不能这样做。 Java 没有这个特性(self-types)。理论上你可以这样做,但为了保证类型安全,它有一些限制。

假设你可以这样做,那么我可以编写这样的代码:

Entity e = new Player();
e.parent.add(new SomeOtherKindOfEntity());

这没有多大意义,不是吗? e 会有一个 ArrayList<Player>,但编译器认为我们可以将 SomeOtherKindOfEntity 添加到它!所以你不能使用类型 Entity 作为变量的类型。

这是另一种类似的情况:

Player p = new SubclassOfPlayer();
p.parent.add(new Player());

实际上,您可以使用通用参数来解决此问题:

public abstract class Entity<T extends Entity<T>> {
  private final ArrayList<T> parent;

  // a lot of code that is not important now
}

public class Player extends Entity<Player> { }

大多数 Java 程序员都会认识到泛型参数的类型与子类本身的类型相同,but the compiler doesn't。这就是为什么这只是一种解决方法,而不是真正的“自我类型”。

答案 1 :(得分:2)

你可以做到这一点。

  1. 我们声明一个泛型 T,然后添加一条规则,即该泛型必须扩展实体类。
  2. Player 类,继承自 Entity,然后就可以使用了。

以下代码...

public abstract class Entity<T extends Entity> {
  private final ArrayList<T> parent;    
}

public class Player extends Entity<Player> {
}

答案 2 :(得分:2)

要实现这一点,您可以将类 Entity 设为通用类。示例:

public abstract class Entity<THIS extends Entity<?>> {

    private final List<THIS> parents = new ArrayList<>();

    public final List<THIS> getParents() {
        return parents;
    }

}

您的子类现在可以如下所示:

public final class Player extends Entity<Player> { ... }

使用它看起来像这样:

public static void main(String[] args) {
    Player player = new Player();
    List<Player> playerParents = player.getParents();
    System.out.println(playerParents);
}

答案 3 :(得分:0)

您可以使用 Object 作为类型。 Java 中的所有类都是Object 类的子类。代码:

public abstract class Entity{
 private final ArrayList<Object> parent;

 // a lot of code that is not important now
}

然后,当引用 ArrayList 时,您只需要将其强制转换为当前类。示例:

(Player) parent.getItem(int itemNumber); 
相关问题