假设我有以下类:
public abstract class Crop {
}
public abstract class Fruit extends Crop {
}
public interface Edible /* ALWAYS IMPLEMENTED BY A CROP */ {
}
public class Apple extends Fruit implements Edible /* BOTH A CROP AND EDIBLE */ {
}
public class Holly extends Fruit /* NOT EDIBLE */ {
}
public class Wheat extends Crop implements Edible {
}
现在,我要确保每个Edible
(接口)都是Crop
(类)。
为什么我不能说:
public interface Edible implements Crop {
}
所以Edible
本身只能通过扩展Crop
的类来实现?
是否有解决方法,特别是当传递Edible
作为需要Crop
的通用参数时?
限制哪些类可以实现接口的唯一选择是使用密封接口(在Java 17中引入),它限制了哪些类可以继承它。然而,您的用例有"问题"。并不是所有的作物都可以食用,这使问题变得复杂。
从表面上看,你的问题是无法解决的,除非你想显式列出接口中所有可能的类。
例如,您的问题可以这样解决
public sealed interface Edible
permits Apple, Wheat {
}
public abstract class Crop {
}
public abstract class Fruit extends Crop {
}
public final class Apple extends Fruit implements Edible /* BOTH A CROP AND EDIBLE */{
}
public class Holly extends Fruit /* NOT EDIBLE */ {
}
public final class Wheat extends Crop implements Edible {
}
您可以使用以下语句来放松一些约束:
public sealed interface Edible
permits EdibleFruit, Wheat {
}
public abstract class Crop {
}
public abstract class Fruit extends Crop {
}
public non-sealed abstract class EdibleFruit extends Fruit implements Edible {
}
public class Apple extends EdibleFruit /* BOTH A CROP AND EDIBLE */{
}
public class Holly extends Fruit /* NOT EDIBLE */ {
}
public final class Wheat extends Crop implements Edible {
}
但这可能导致一个复杂的层次结构(例如,考虑一些可食用水果的子类型是不可食用的)。
不同的处理方式可能更有意义,例如检查可食性或毒性,或最大安全剂量,或类似的东西。
不能在接口上实现Java类。接口只能extend
其他接口。因此,通过这种方式,您可以声明另一个接口(并在Crop
上实现它)。然后,您可以在Editable
上扩展这个新接口。
可以是这样的:
public abstract class Crop implements NewInterface{
}
public interface Edible extends NewInterface {
}
为什么不约束Edible
?
interface Edible<T extends Crop> {}
使每个可食用的必须实例化接口,如果它子类Crop
:
class A extends Crop implements Edible<A> {} // Ok
class B implements Edible<B> {} // Bad
至少每个Edible
都需要用一个Crop
类实例化。但是你可以做一些奇怪的事情,比如:
class C implements Edible<A> {}