我有几个类,我有强制执行的公共setter方法。
我可以使用abstract
类显式定义setter,然后扩展该类,或我可以实现interface
。但是使用interface
我必须一遍又一遍地编写setter方法,这似乎违反了DRY原则。
public abstract class AbstractParent {
int value;
protected void setValue(int value) {
this.value = value;
}
}
VS
public interface MyInterface {
void setValue(int value);
}
何时使用哪种方法有意义?
答案 0 :(得分:2)
最抽象的("最佳")方式是使用两者:
// The contract
public interface MyInterface {
void setValue(int value);
}
// A convenient implementation from which to base a concrete implementation
public abstract class AbstractParent implements MyInterface {
int value;
void setValue(int value) {
this.value = value;
}
}
您可以在整个JDK中看到此模式,例如:
interface Map {...
abstract class AbstractMap implements Map {...
class HashMap extends AbstractMap {...
此模式允许编码器提供符合合同的自己的类,这在使用这些对象的单元测试代码时尤为重要,因为它更容易模拟接口而不是类,可能是最终的,具有私有构造函数或其他不方便的特性。
答案 1 :(得分:1)
对于您的场景,使用抽象类来定义setter的常用功能更有意义,特别是如果子类的所有setter都相同的话。
使用抽象类,您可以定义一次公共setter并完成它。如果需要,您可以指定(使用抽象函数)仅需要存在的特定函数,并且每个子类都是唯一的。
使用接口,其中的每个方法基本上都是抽象的,因此您将被迫为每个子类一遍又一遍地编写每个方法。对于每个子类,都需要重复对setter的任何未来更改。复制粘贴错误或在更新时忘记错误可能是灾难性的。
如果您正在寻求强制执行模板而不重复自己,那么抽象类就是这里的方法。
答案 2 :(得分:0)
在你的情况下,如果你想要一个没有实现的纯合同,或者你的子类必须已经扩展另一个类而你因为一个类不能而烦恼,那么应该使用Interface
而不是abstract
类扩展了两个类。
如果不是这样,抽象类就足够了 当你可以轻松做事时,不要复杂化。
答案 3 :(得分:0)
这就是拇指规则 1.当您想要从客户端(子)类移动常见实现时使用抽象类,否则不使用抽象,因为java只提供了一个要扩展的类。 2.使用接口类强制客户端类来实现行为,以便客户端类仍然可以根据需要扩展其他类。
public interface SetterInterface {
void setValue(int value);
}
// Here MyClass is can still extend any other class if needed,
class MyClass implements SetterInterface {
答案 4 :(得分:0)
最好使用合成而不是继承。 你可以将这个值和setter拉出到另一个类中,然后将这个类的实例作为其他类中的成员。 它比继承层次结构更加清晰