在Java中,我应该对常量属性使用getter还是接口标记?
假设我正在用Java为不同的动物建模。每种动物都有这些能力的组合:行走、游泳和飞翔。例如,能力集是常量 我可以将此信息存储为返回常量的getter。例如:在Java中,我应该对常量属性使用getter还是接口标记?,java,oop,design-patterns,interface,Java,Oop,Design Patterns,Interface,假设我正在用Java为不同的动物建模。每种动物都有这些能力的组合:行走、游泳和飞翔。例如,能力集是常量 我可以将此信息存储为返回常量的getter。例如: public class Penguin implements Animal { public boolean canWalk() { return true; } public boolean canSwim() { return true; } public b
public class Penguin implements Animal {
public boolean canWalk() {
return true;
}
public boolean canSwim() {
return true;
}
public boolean canFly() {
return false;
}
// implementation...
}
运行时检查是:
if (animal.canFly()) {
// Fly!
}
if (animal instanceof Flyer) {
// Fly!
}
或者我可以使用“标记”界面:
public class Penguin implements Animal, Flyer, Swimmer {
// implementation...
}
运行时检查是:
if (animal.canFly()) {
// Fly!
}
if (animal instanceof Flyer) {
// Fly!
}
每种方法的优缺点是什么 标记接口在现代Java中有点反模式,在早期是必需的,因为无法直接向类添加元数据。“现代”方法是:
@Retention(RetentionPolicy.RUNTIME)
@interface Flyer {
}
@Retention(RetentionPolicy.RUNTIME)
@interface Swimmer {
}
@Flyer @Swimmer
public class Penguin implements Animal {
}
以及运行时检查:
if(Animal.class.isAnnotationPresent(Flyer.class)) {
// fly!
}
如果您只想知道一只动物是否具有这种特性,即飞行和游泳能力是纯元数据,则可以使用这种方法
你想达到什么目标?我不会称之为OOP,因为OOP方法通常不是查询功能和执行特定于对象的条件逻辑,而是使用多态性。行走/游泳/飞行功能与种类或状态相关吗?这是类标记(种类)和属性(状态)之间的真正区别
您必须注意,类一旦被标记,就永远不能被“取消标记”。所有子类都将从中继承。这同样适用于单个实例,因为它不能动态更改其类型(至少在Java中是这样)
另一个评论与抽象有关。标记要求其他API了解标记类型(接口、类或注释)。而有些API只需要依赖“抽象接口”(即方法名)。JavaBean感知约定的API就是这样的例子。集成将比编写特定方法来检查类继承或注释的存在更容易
总之,静态功能(如Runnable
命令)可以依赖于类标记,而动态功能必须依赖于状态。您需要注释接口的一个参数才能在运行时使用。@Dariusz很好!注释是标记接口的替代品,这是一种常见的误解。有效的Java项目#37:使用标记接口定义类型,特别指出标记接口相对于注释的优势。