我正在设计一个接口,我打算按照有效Java (Joshua Bloch)来获得一个抽象类或骨架类。第18项:首选接口到抽象类。
原因是为了防止界面的未来发展破坏实施类。
截至今天,我没有任何方法可以为其提供默认实现。这个设计好吗?
例如:
public interface Foo{
public List<Baz> getBazList();
public String getId();
public String getName();
}
public abstract class AbstractFoo implements Foo{
}
答案 0 :(得分:1)
您可以在此案例和类似案例中应用简单但功能强大的测试。
问自己这个问题:“我如何在我的代码中使用这个抽象类?我打算如何使用我的界面无法使用它?”
如果答案是“没有”,那么就摆脱它。如果构造没有任何实际意义,它只会给代码增加混乱。
答案 1 :(得分:0)
如果您认为将来可能会扩展接口,从而导致子类不兼容(因为它们没有实现这些方法),那么使用该空的抽象超类可能是一种使其能够轻松编译的方法。 / p>
即。今天你有
public interface Foo{
public List<Baz> getBazList();
public String getId();
public String getName();
}
public abstract class AbstractFoo implements Foo{
}
public class Foo1 extends AbstractFoo {
public List<Baz> getBazList() { ... }
public String getId() { ... }
public String getName() { ... }
}
public class Foo2 extends AbstractFoo {
public List<Baz> getBazList() { ... }
public String getId() { ... }
public String getName() { ... }
}
将来,有人会更改界面(无论出于何种原因),因此您需要执行以下操作:
// extended
public interface Foo{
public List<Baz> getBazList();
public String getId();
public String getName();
public void breakMyCode();
}
// provide dummy implementation for breakMyCode()
public abstract class AbstractFoo implements Foo{
public void breakMyCode() {
throw new RuntimeException("not implemented");
}
}
// unchanged
public class Foo1 extends AbstractFoo {
public List<Baz> getBazList() { ... }
public String getId() { ... }
public String getName() { ... }
}
// unchanged
public class Foo2 extends AbstractFoo {
public List<Baz> getBazList() { ... }
public String getId() { ... }
public String getName() { ... }
}
这是个好主意吗?并不是的。当接口扩展时,可能有一个原因,并且只提供一个无效或抛出RuntimeException的虚拟实现不会使程序按预期工作。它是一种在编译期间隐藏省略的方法,但让它们在运行时中断程序。