【发布时间】:2019-01-09 12:56:33
【问题描述】:
好的,所以我正在尝试为此找出最佳结构。我想知道什么是这些情况下的最佳做法以及总体上最有效的做法。
问题
假设我正在创建一个小世界。这个世界由不同类型的鸟类组成,所以我创建了一个 Bird 类来充当所有鸟类的父母。
public abstract class Bird {
//stuff all birds have in common
}
现在我想创建不同类型的鸟。让我们创建一个 Penguin 和一个 Goose 类并让它们扩展 Bird。
public class Penguin extends Bird{
//penguin stuff
}
public class Goose extends Bird{
//goose stuff
}
到目前为止一切顺利,但现在是扳手。让我们赋予鸟类飞行的能力。 惊喜,不是所有的鸟都会飞——比如企鹅!那么让我们来看看我们的选择吧..
在 Bird 类中创建 fly 方法是不可能的(不是所有的鸟都会飞)。另一种糟糕的方式是拥有多个父类,例如 BirdsThatFly,因为这会变得非常混乱,尤其是当其他 birdly 属性添加到混合中时。
选项 1
接口
一个可行的选择是使用接口,理论上听起来是正确的想法。例如,我可以有一个 Fly 接口。
public interface Fly {
public void fly();
}
这将允许我仅在可以飞行的 Bird 子类上实现 Fly。例子..
public class Goose extends Bird implements Fly {
@Override
public void fly() {
//fly!
}
}
这看起来很干净,并强制在 goose 上使用 fly 方法,并且在添加其他属性时似乎可以很好地工作。
似乎有问题的是,我仍然需要为每种类型的鸟创建一个自定义苍蝇,而且可能会有很多鸟!默认空缺对我有帮助吗?我觉得随着这些属性的增长,它们可能会受到相当大的限制。
也许可以告诉我其他情况以及如何重新考虑这个接口结构。
选项 2
我自己的属性类
这涉及创建属性对象并将它们添加到各个鸟类类中。如果我对接口的看法是正确的,那么这个选项可能是一种有效的方法。
属性类看起来像这样
public abstract class Attribute {
public abstract void execute();
}
一个属性可能看起来像这样
public class Fly extends Attribute{
@Override
public void execute() {
//fly!
}
}
现在可以通过在 Bird 中拥有一个属性列表并将其填充到鸟类类型类中来将这个 fly 属性添加到鸟类。
public abstract class Bird {
private List<Attribute> attributes = new ArrayList<Attribute>();
protected void addAttribute(Attribute attribute){
attributes.add(attribute);
}
public List<Attribute> getAttributes(){
return attributes;
}
}
并将其添加到 Goose...
public class Goose extends Bird{
public Goose(){
super.addAttribute(new Fly());
}
}
对我来说,这种方法似乎非常可定制,但也似乎不实用,并且可能无法立即清楚每个班级能够做什么。它还需要大量工作才能在更大规模上正确设置才能执行特定属性。
有没有一种方法可以被认为是更好的做法,或者这些方法中的任何一种是合理的方法还是一个好的开始?
【问题讨论】:
-
我认为常规的做法是使用 1 和 2 的组合:在单独的类中实现功能并通过共享接口将其公开。缺点是它可能会导致大量样板文件。我在类似的场景中使用了默认方法,但这有它自己的警告。
-
您可能想要的是Mixin。这些在 Java 中实现起来有点困难,但是有一些库可以添加这种支持,例如 Apache Polygene。
-
有趣的是,飞行是鸟(不是人类)的属性,在面向对象的术语中它是一种行为!
标签: java oop inheritance interface abstract