猿问

接口和抽象类的属性继承 - Java

好的,所以我试图找出最好的结构。我想知道在这些情况下什么被认为是最佳实践,并且总体上最有效。


问题

假设我正在创造一个小世界。这个世界由不同类型的鸟类组成,所以我创建了一个 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,因为这会变得非常混乱,尤其是当其他鸟类属性添加到组合中时。


选项1

接口

一种在理论上听起来是正确想法的可行选择是使用接口。例如,我可以有一个 Fly 界面。


public interface Fly {

    public void fly();

}

这将允许我仅在可以飞行的 Bird 子类上实现 Fly。例子..


public class Goose extends Bird implements Fly {

    @Override

    public void fly() {

        //fly!

    }

}

这看起来很干净并强制使用 fly 方法到 goose 上,并且在添加其他属性时它似乎可以很好地工作。


似乎错误的事情是,我仍然必须为每种类型的鸟创建一个自定义的苍蝇,而且可能有很多鸟!默认空位会在这里帮助我吗?我觉得随着这些属性的增长,它们可能会受到相当大的限制。


也许我可以被告知如何重新思考这个界面结构。


选项 2

我自己的属性类

这涉及创建属性对象并将它们添加到各个鸟类类中。如果我对接口是正确的,这个选项可能是一种有效的方法。


属性类看起来像这样


public abstract class Attribute {

    public abstract void execute();

}

一个属性可能看起来像这样


public class Fly extends Attribute{

    @Override

    public void execute() {

        //fly!

    }

}

现在可以通过在 Bird 中拥有一个属性列表并将其填充到鸟类类型类中来将此飞属性添加到鸟类中。


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;

    }

}

并将其添加到鹅...


public class Goose extends Bird{

    public Goose(){

        super.addAttribute(new Fly());

    }

}

这种方法对我来说似乎非常可定制,但也似乎不合时宜,可能无法立即清楚每个类能够做什么。它还需要大量工作才能在更大范围内正确设置才能执行特定属性。


有没有一种方法可以被认为是更好的做法,或者这些方法是合理的方法还是好的开始?


慕森卡
浏览 159回答 2
2回答

POPMUISE

这只是围绕面向对象设计的一些基本思想。如果没有更具体的信息,就很难就设计类或接口做出明确的决定。继承、行为和属性主要影响设计。设计的方式还取决于大小(数量、类型和种类 - 请记住)。可以看看 Java 语言本身的继承设计,例如集合——Collection接口和Map接口及其实现。以下是一些即时的想法:public interface Bird {&nbsp; &nbsp; public void eat();&nbsp; &nbsp; public void layEggs();}// Provides implementations for _some_ abstract methods and _no_ new methods.// Also, some implementations can just be empty methods.public abstract class AbstractBird implements Bird {&nbsp; &nbsp; public void eat() {&nbsp; &nbsp; &nbsp; &nbsp; // generic eating implementation&nbsp; &nbsp; }&nbsp; &nbsp; public abstract void layEggs(); // no implementation at all}// Specific to ground-oriented with Bird behaviourpublic interface GroundBird extends Bird {&nbsp; &nbsp; public void walk();}// Specific to air-oriented with Bird behaviorpublic interface FlyBird extends Bird {&nbsp; &nbsp; public void fly();}// Ground-oriented with _some_ bird implementation&nbsp;public class Penguin extends AbstractBird implements GroundBird {&nbsp; &nbsp; public void walk() {&nbsp; &nbsp; }&nbsp; &nbsp; public void layEggs() {&nbsp; &nbsp; &nbsp; &nbsp; // lays eggs on ground&nbsp; &nbsp; }&nbsp; &nbsp; // Can override eat if necessary}// Air-oriented with _all_ bird implementation&nbsp;public class Eagle implements FlyBird {&nbsp; &nbsp; public void fly() {&nbsp; &nbsp; }&nbsp; &nbsp; public void layEggs() {&nbsp; &nbsp; &nbsp; &nbsp; // lays eggs on trees&nbsp; &nbsp; }&nbsp; &nbsp; public void eat() {&nbsp; &nbsp; &nbsp; &nbsp; // can eat while flying&nbsp; &nbsp; }}这种设计将允许:提供更多的方法,例如pluck()在Bird后来接口,只在有执行AbstractBird。也有一些类别的类可以跳过AbstractBird完全和直接实现Bird接口的更具体的实施方式eat和layEggs。这也允许一个新的鸟类扩展一个新的类或抽象类。WaterBirds稍后添加其他类型的鸟,例如*。*public interface WaterBird {&nbsp; &nbsp; public void swim();}public class Duck implements WaterBird, GroundBird {&nbsp; &nbsp; public void swim() {&nbsp; &nbsp; }&nbsp; &nbsp; public void walk() {&nbsp; &nbsp; }&nbsp; &nbsp; public void eat() {&nbsp; &nbsp; }&nbsp; &nbsp; public void layEggs() {&nbsp; &nbsp; &nbsp; &nbsp; // lays eggs on ground&nbsp; &nbsp; }}并且可以Diveable为可以潜入水中捕鱼Glideable的鸟类以及可以翱翔和滑翔的鸟类创建新的界面。可以看到的Glideable是飞鸟的一种特殊行为。另请注意,这Glidable也是HangGlider 的一种行为,由鸟类和飞机共享。public interface Glideable {&nbsp; &nbsp; public void glide();}public class Eagle extends AbstractBird implements FlyBird, Glideable {&nbsp; &nbsp; public void fly() {&nbsp; &nbsp; }&nbsp; &nbsp; public void glide() {&nbsp; &nbsp; &nbsp; &nbsp; // eagle specific&nbsp; &nbsp; }&nbsp; &nbsp; public void layEggs() {&nbsp; &nbsp; &nbsp; &nbsp; // lays eggs on trees&nbsp; &nbsp; }&nbsp; &nbsp; // Can override eat if necessary}注意:从 Java 8 开始,可以考虑在接口中使用静态和默认方法。
随时随地看视频慕课网APP

相关分类

Java
我要回答