use*_*409 9 java abstract-class interface
上周末我读了一些关于接口,抽象类和设计原则的东西.最后我有点困惑,我试图建立一个我学到的(或者我以为我学到的)的例子.
这是我的例子:案例是模拟一个包含有关树的信息的类.
首先,我会做一个界面:
public interface Tree{
public void grow();
}
Run Code Online (Sandbox Code Playgroud)
该接口包含应由具体树实现的所有方法.到目前为止这么好,但是这样的树需要一些在所有树家族上共享的属性(变量).为此,我将使用一个抽象类:
public abstract class AbstractTree implements Tree {
private String barColor;
private int maxHeight;
private boolean isEvergreen;
}
Run Code Online (Sandbox Code Playgroud)
这是正确的方式,还是我不能就其他类中的属性(变量)签订合同?
属性部分完成后,我希望有3种类型的树.
因此,这些树"tpyes"中的每一个都可以具有单独的变量.
public class OakTreeImpl extends AbstractTree{
private String barColor;
private int maxHeight;
private boolean isEvergreen;
private String foo;
@Override
public void grow() {
}
}
Run Code Online (Sandbox Code Playgroud)
这种方法在面向对象的设计原则中是否正确,或者我完全错了吗?
这确实有效,但它没有多大意义,因为在这种情况下接口完全过时了.
您应该将grow方法添加到您的AbstractTree
喜欢:
public abstract class AbstractTree{
protected String barColor;
protected int maxHeight;
protected boolean isEvergreen;
public abstract void grow();
}
Run Code Online (Sandbox Code Playgroud)
如果你想拥有不同种类的植物,那么使用界面就有意义了.
interface Plant{
void grow();
}
abstract class Tree implements Plant{
void grow(){ /* do sth */ }
}
abstract class Flower implements Plant{
void grow(){ /* do sth totally different */
}
Run Code Online (Sandbox Code Playgroud)
接口的目的是在具有不同实现的多个类中提供相同的方法,而抽象类提供在其所有子类中共享的方法和属性.
如果抽象类中的方法也是抽象的,则每个子类都必须自己实现它.
我宁愿将实例变量标记为protected
.
因为子类可以访问超类的所有受保护成员.当且仅当,父类和子类在同一个包中
public abstract class AbstractTree implements Tree {
protected String barColor;
protected int maxHeight;
protected boolean isEvergreen;
}
public class OakTreeImpl extends AbstractTree{
// I can access barColor, maxHeight, isEvergreen in this class
@Override
public void grow() {
}
}
Run Code Online (Sandbox Code Playgroud)
尽管这可能是部分主观的,但我必须同意到目前为止给出的其他答案。
该Tree
接口不是过时的。当您要为建模时Tree
,应该有一个Tree
接口,明确说明每个接口Tree
都有的方法。
特别是,我建议不要将其简单地替换为AbstractTree
类。有人说,你应该很难使用抽象类在所有(例如雅罗斯拉夫Tulach在“实用API设计”)。我至少要说您应该非常保守地使用它们。最重要的是:您应尽量避免让抽象类出现在其他类的公共接口中。例如,如果您有另一个类/接口,则使用类似
void makeGrow(Tree tree) {
System.out.println("Growing "+tree);
tree.grow();
}
Run Code Online (Sandbox Code Playgroud)
然后更换的这个外观Tree
来AbstractTree
将降低灵活性。您将永远无法使用不继承自一个类的类AbstractTree
-考虑到您只能继承一个类,这可能是一个严重的限制。(您始终可以实现多个接口-因此,这里的接口并不限制灵活性)。
但是,即使如果您使用抽象类的基础,我建议使用protected
保守的领域。或者,更一般而言,请注意从类继承的含义,如Joshua Bloch的“ Effective Java”的“第17项-继承的设计和文档”中所述。
在许多情况下,您不希望继承的类具有对字段的完全访问权限。因此,您至少应该考虑创建字段private
,并且仅提供protected
要授予继承类访问权限的方法。
public interface Tree{
public void grow();
}
abstract class AbstractTree implements Tree {
// Do the values of these fields ever change? If not,
// then make them final, and set them only in the
// constructor
private final String barColor;
private final int maxHeight;
private final boolean evergreen;
protected AbstractTree(...) { ... }
// Subclasses are only allowed to read (but not write) these fields
protected final String getBarColor() { return barColor; }
protected final intgetMaxHeight() { return maxHeight; }
protected final boolean isEvergreen() { return evergreen; }
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
2613 次 |
最近记录: |