Java 在接口中实现 class
Java implement class in interface
假设我有以下 classes:
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
(class)。
为什么我不能说:
public interface Edible implements Crop {
}
所以 Edible
本身只能由扩展 Crop
?
的 classes 实现
是否有解决此问题的方法,尤其是在将 Edible
作为需要 Crop
的通用参数传递时?
您不能在接口上实现 Java Class。接口只能 extend
其他接口。因此,通过这种方式,您可以声明另一个接口(并在 Crop
上实现它)。然后,您可以在 Editable
.
上扩展这个新接口
这可以是这样的:
public abstract class Crop implements NewInterface{
}
public interface Edible extends NewInterface {
}
限制 classes 可以实现接口的唯一选项是使用 sealed interface(在 Java 17 中引入),它限制了 class 可以继承的内容它。但是,您的 use-case 存在并非所有农作物都可食用的“问题”,这使事情变得复杂。
从表面上看,您的问题无法解决,除非您想在界面中明确列出所有可能的 classes。
例如,你的问题可以这样解决
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 {
}
但这可能会导致复杂的层次结构(例如,考虑到某些 sub-types 可食用水果是不可食用的)。
以不同的方式处理这个问题可能更有意义,例如检查可食性或毒性,或最大安全剂量,或类似的东西。
为什么不约束Edible
?
interface Edible<T extends Crop> {}
所以每个可食用的都必须实例化接口,如果它是子class Crop
:
class A extends Crop implements Edible<A> {} // Ok
class B implements Edible<B> {} // Bad
至少每个 Edible
都需要用 class 实例化,即 Crop
。但是你可以做一些奇怪的事情,比如:
class C implements Edible<A> {}
假设我有以下 classes:
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
(class)。
为什么我不能说:
public interface Edible implements Crop {
}
所以 Edible
本身只能由扩展 Crop
?
是否有解决此问题的方法,尤其是在将 Edible
作为需要 Crop
的通用参数传递时?
您不能在接口上实现 Java Class。接口只能 extend
其他接口。因此,通过这种方式,您可以声明另一个接口(并在 Crop
上实现它)。然后,您可以在 Editable
.
这可以是这样的:
public abstract class Crop implements NewInterface{
}
public interface Edible extends NewInterface {
}
限制 classes 可以实现接口的唯一选项是使用 sealed interface(在 Java 17 中引入),它限制了 class 可以继承的内容它。但是,您的 use-case 存在并非所有农作物都可食用的“问题”,这使事情变得复杂。
从表面上看,您的问题无法解决,除非您想在界面中明确列出所有可能的 classes。
例如,你的问题可以这样解决
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 {
}
但这可能会导致复杂的层次结构(例如,考虑到某些 sub-types 可食用水果是不可食用的)。
以不同的方式处理这个问题可能更有意义,例如检查可食性或毒性,或最大安全剂量,或类似的东西。
为什么不约束Edible
?
interface Edible<T extends Crop> {}
所以每个可食用的都必须实例化接口,如果它是子class Crop
:
class A extends Crop implements Edible<A> {} // Ok
class B implements Edible<B> {} // Bad
至少每个 Edible
都需要用 class 实例化,即 Crop
。但是你可以做一些奇怪的事情,比如:
class C implements Edible<A> {}