有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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现在抱怨BaseEnclosureBaseAnimal是原始类型。如果我写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) 个答案

  1. # 1 楼答案

    I want to specify that when CatEnclosure.resettleTo(Enclosure) is called, only one Cat Enclosure can be passed. In my current code, a cat could also be placed with a dog.

    假设在这里,您不希望CateConSure重置为DogEnclosure

    您的场景是泛型中循环引用的典型案例。基于此post,您需要按如下方式重新定义基类:

    public abstract class BaseAnimal<A extends BaseAnimal<A, E>, E extends BaseEnclosure<E, A>> {...}
    
    public abstract class BaseEnclosure<E extends BaseEnclosure<E, A>, A extends BaseAnimal<A, E>> {...}
    
    class Dog extends BaseAnimal<Dog, DogEnclosure> {...}
    class DogEnclosure extends BaseEnclosure<DogEnclosure, Dog> {...}
    // Similarly Cat and CatEnclosure
    

    现在,为了防止cat机柜重置为dog机柜,您需要更改resettleTo方法签名,如下所示:
    public abstract void resettleTo(BaseEnclosure<E,A> other);

    您将不被允许编译以下代码:

    CatEnclosure catEnclosure = new CatEnclosure();
    Cat c = new Cat();
    c.setEnclosure(catEnclosure);
    
    DogEnclosure dogEnclosure = new DogEnclosure();
    Dog d = new Dog();
    d.setEnclosure(dogEnclosure);
    
    catEnclosure.resettleTo(dogEnclosure); // Error type mismatch