java类继承和泛型类型
我目前正在研究Java中的继承。我想和你讨论一下下面的情况
在我的例子中,我有许多动物和圈地类。所有动物均来源于BaseAnimal
。所有存储模块都派生自BaseEnclosure
。这两个基类都提供了各种具体方法,但也提供了一些抽象方法
现在,在实现CatEnclosure
时,我想指定在调用CatEnclosure.resettleTo(Enclosure)
时,只能传递一个cat存储模块。在我目前的代码中,猫也可以和狗放在一起
据我所知,在BaseEnclosure
类中创建抽象方法resettleTo
时,我必须定义未来(派生)类的类
我的想法是使用第二种通用方法。所以BaseEnclosure<A>
变成了BaseEnclosure<E, A>
。但是现在我还必须指定E
必须从BaseEnclosure
派生。此外,当然,A
也应该是BaseAnimal
类型
所以我得到:BaseEnclosure<E extends BaseEnclosure, A extends BaseAnimal>
我的IDE现在抱怨BaseEnclosure
和BaseAnimal
是原始类型。如果我写BaseEnclosure<E extends BaseEnclosure<?,?>, A extends BaseAnimal<?,?>>
,它会工作。然而,我不知道所有这些在设计方面是否有意义
我期待你的建议
随函附上示例代码
public abstract class BaseAnimal<E> {
protected E enclosure;
public void setEnclosure(E enclosure) {
this.enclosure = enclosure;
}
public E getEnclosure() {
return enclosure;
}
public abstract String getNoise();
}
public abstract class BaseEnclosure<A> {
protected List<A> animals = new ArrayList<A>();
// some methods...
public List<A> getAnimals() {
return animals;
}
public abstract void resettleTo(BaseEnclosure other);
}
public class Cat extends BaseAnimal<CatEnclosure> {
@Override
public String getNoise() {
return "miiiaaauu";
}
}
public class CatEnclosure extends BaseEnclosure<Cat>{
@Override
public void resettleTo(BaseEnclosure other) {
// hm...
}
}
public class Dog extends BaseAnimal<DogEnclosure> {
@Override
public String getNoise() {
return "wuff";
}
}
public class DogEnclosure extends BaseEnclosure<Dog>{
// some methods...
@Override
public void resettleTo(BaseEnclosure other) {
// hm...
}
}
public class Main {
public static void main(String[] args) {
DogEnclosure doghouse = new DogEnclosure();
Dog dog = new Dog();
// later: JPA
doghouse.getAnimals().add(dog);
dog.setEnclosure(doghouse);
CatEnclosure catbox = new CatEnclosure();
Cat cat = new Cat();
// later: JPA
catbox.getAnimals().add(cat);
cat.setEnclosure(catbox);
// OHOHOH!!!
doghouse.resettleTo(catbox);
}
}
# 1 楼答案
假设在这里,您不希望CateConSure重置为DogEnclosure
您的场景是泛型中循环引用的典型案例。基于此post,您需要按如下方式重新定义基类:
现在,为了防止cat机柜重置为dog机柜,您需要更改resettleTo方法签名,如下所示:
public abstract void resettleTo(BaseEnclosure<E,A> other);
您将不被允许编译以下代码: