使用java泛型来确保接收的参数与其类或子类型相同

Kil*_*ahn 9 java generics

我有一个新手问题.

interface Animal {
    void partner(Animal other);
}

class Lion implements Animal {
    int areaUnderControl;
    @Override
    public void partner(Animal other) {
        Lion lion = (Lion) other;
        this.areaUnderControl += lion.areaUnderControl; 
    }
}

class Human implements Animal {
    int money;
    @Override
    public void partner(Animal other) {
        Human human = (Human) other;
        this.money += human.money;
    }
}
Run Code Online (Sandbox Code Playgroud)

我希望具体实现中的伙伴方法只接收其类型或其子类型的参数.一种解决方案是使用泛型将Animal定义为:

interface Animal<T extends Animal<T>> {
    void partner(T other);
}

class Lion implements Animal<Lion> {
    int areaUnderControl;
    @Override
    public void partner(Lion other) {
        this.areaUnderControl += other.areaUnderControl; 
    }
}

class Human implements Animal<Human> {
    int money;
    @Override
    public void partner(Human other) {
        this.money += other.money;
    }
}
Run Code Online (Sandbox Code Playgroud)

但是有人仍然可以滥用这个

class Bear implements Animal<Lion> {
    int honey;
    @Override
    public void partner(Lion other) {
        this.honey += other.areaUnderControl; //Problem
    }
}
Run Code Online (Sandbox Code Playgroud)

Bear正渴望与Lion合作.有什么方法,我可以把它绑的类型和亚型

我尝试搜索现有的问题,不知怎的,我觉得界面本身的设计可能有缺陷.如果有人能够指出为什么这是错误的或正确的方法来实现这一目标,我们将不胜感激.

谢谢!

new*_*cct 2

无法在接口级别强制执行此操作,因为从类型安全的角度来看没有理由这样做。那么如果可以定义 aclass Bear implements Animal<Lion>呢?就其本身而言,它是类型安全的(即不会抛出意外的 ClassCastException 等)——这就是泛型的全部意义所在。

事实上,从类型安全的角度来看,很可能您只需要interface Animal<T>(类似于interface Comparable<T>)。是的,这将允许某人定义奇怪的类,这些类使用完全不相关的类的类型参数来实现 Animal。所以呢?这本身并没有什么问题。

在使用此接口的地方,他们可以强制执行您想要的关系,例如public <T extends Animal<? super T>> void someMethodThatUsesAnimal(T animal). 因为只有在使用它的地方才真正关心该partner方法是否将自身作为参数。这类似于如何Comparable使用(例如public <T extends Comparable<? super T>> void sort(List<T> list)