与泛型实现父子关系

时间:2018-12-28 22:26:29

标签: java generics

我正在尝试制作一个容器(父)对象,您可以在其中指定其可以包含的对象(子对象)的类型。

类似地,您可以指定孩子的父母的类型。 父母和孩子将来需要进行交流,因此我需要他们俩都具有彼此的对象引用。

此代码是我应用中实际代码的简单表示。

class Parent<T extends Child> {
    ArrayList<T> childObjects;
    public void addChildChild(T newChild) {
        childObjects.add(newChild);
        newChild.setParent(this);
    }
    public void newChildConnected(T connectedChild) {
        System.out.println("Child connected");
    }
}

class Child <T extends Parent> {
    T parentObject;
    public void setParent(T newParent) {
        parentObject = newParent;
        parentObject.newChildConnected(this);
    }
}

我的IDE说:     未经验证的原始类型“ test.Parent”成员对“ newChildConnected(T)”的调用

我一直在尝试通过通配符和其他东西使它更好的方法,但是我尽力而为。 那么实现这种行为的正确方法是什么?

我的目标是能够为父级指定子类型,为子级指定父类型,并以子级和父级能够使用彼此功能的方式进行操作,而无需使用intanceof()运算符和强制转换。 (这就是我毕竟使用泛型的原因)

在Java中甚至可能吗?

2 个答案:

答案 0 :(得分:1)

您对通用类型的使用会创建一个循环类型引用。如果父级和子级的类型(或接口/基类)相同,请在单个类中使用树结构:

class MyObject<T> {
T parentObject;
ArrayList<T> childObjects = new ArrayList();
public void addChildChild(T newChild) {
    childObjects.add(newChild);
    newChild.setParent(this);
}
public void newChildConnected(T connectedChild) {
    System.out.println("Child connected");
}
public void setParent(T newParent) {
    parentObject = newParent;
    parentObject.newChildConnected(this);
}

使用此类时,必须检查parentObject == null处的顶级对象和childObjects.size()==0处的叶对象。

如果没有通用接口或基类,则无法安全地完成此操作。

答案 1 :(得分:1)

正如@Strom正确指出的那样,如果没有基类或接口,就不能以类型安全的方式完成此操作。

如果您可以扩展类/接口,则无需任何强制类型转换的类型安全解决方案将如下所示:

"dependencies": {
    "native-base": "^2.13.8",
    "react": "16.9.0",
    "react-native": "0.61.2",
    "react-native-maps": "git+https://git@github.com/react-native-community/react-native-maps.git"
}```

该解决方案使用"recursive" generics来确保类型安全,并使用self-type reference来避免强制类型转换。这两种方法都有警告,并且也不是完全安全的,因为您必须依靠基类/类接口的实现者来返回正确的自身类型并定义正确的类型参数,但对于内部API来说应该足够好。