如何在Java中对接口声明应用更多约束?

Jas*_* Hu 37 java generics interface

假设我有以下界面:

interface Mammal {
    void marry(Mammal m);
    Mammal giveBirthTo();
}
Run Code Online (Sandbox Code Playgroud)

但是,这并不完全是我想要的.

显然,人类不能嫁给狗,也不能生出一只猫.那么如何将这些信息嵌入到界面中,以便输入类型和输出类型可以在实现时自动更改?

Men*_*ena 47

您可以使用泛型并更改您的设计.

有些东西:

interface Marriable<T extends Mammal> {
    void marry(T sweetHalf);
    T giveBirthTo();
}
Run Code Online (Sandbox Code Playgroud)

...这里Mammal是你的顶级接口或抽象类,和Human,Dog,Unicorn等扩展/实现它.

  • @RafaelWinterhalter你的方法中的问题是它混合了结婚和物种的范围."哺乳动物"的例子并不是最好的解释,但想象一下`HappyToBeSingleHuman`或'JustPlainUglyHuman`.他们会扩展/实施"哺乳动物"而不是"可婚". (3认同)
  • 界面不应该被命名为"哺乳动物"吗?没有理由添加另一个. (2认同)

Raf*_*ter 23

您可以使用递归类型变量来泛化您的界面:

interface Mammal<T extends Mammal<T>> {
  void marry(T m);
  T giveBirthTo();
}
Run Code Online (Sandbox Code Playgroud)

这样,Java编译器可以为您提供一定的验证级别.但请注意,此方法仍然可以滥用.例如:

class Cat implements Mammal<Cat> {
  @Override void marry(Cat cat) { ... }
  @Override Cat giveBirthTo() { ... }
}

class Dog implements Mammal<Cat> { // implements wrong interface
  @Override void marry(Cat cat) { ... }
  @Override Cat giveBirthTo() { ... }
}
Run Code Online (Sandbox Code Playgroud)

编译器只能确保您Mammal通过同一接口的某个子类型实现接口,而不是通过实现它的特定类来实现.后一种类型约束不能用Java编程语言表示.

  • 对于您的谷歌搜索乐趣,这被称为*F-有界量化*. (5认同)