java接口不考虑来自超类的方法实现

c8ib6hqw  于 2021-07-06  发布在  Java
关注(0)|答案(3)|浏览(373)

下面的ducks示例基于head-first设计模式手册。
我和不同类型的鸭子玩游戏。这里有一只超级级的鸭子,它有两种行为:苍蝇和呱呱,它们被储存在田野里。具体类决定(在构造器中)一个具体品种的行为(参见malardduck类)。
我意识到我希望我的ducks不仅具有duck类型,而且还具有quackable类型(这样我就可以拥有只接受quackables的方法——假设还有其他类型是quack类型——请参见lake类)。当我在mallardduck中实现接口时,编译器抱怨这个类没有方法quack,尽管它是在它的超类duck类中定义的。
现在我可以想出两个解决办法:
通过从超类调用方法来覆盖方法庸医:super.quack()<-但这似乎是不必要的(理论上)-子类可以直接访问超类的公共方法,那么为什么接口庸医甚至抱怨。。。?
makeduck实现quackable->这是相当不合逻辑的,因为有些duck不嘎嘎(它们的嘎嘎行为是用siletnquack类实现的)。
然而,在这两种解决方案中,鸭子:
有古怪的行为,并且
是一个摇摇晃晃的人
这不是根本错误吗?我错过了什么?

abstract class Duck{
    protected Flyiable flyBehaviour;
    protected Quackable quackBehaviour;
    public void quack(){
        quackBehaviour.quack();
    }
    void performFly(){
        flyBehaviour.fly();
    }
    void swim(){
        // swimming implementation
    }
    abstract void display();
}
interface Quackable{
    void quack();
}
class Quack implements Quackable{

    @Override
    public void quack() {
        System.out.println("Quack!");
    }
}
class Quack implements Quackable{

    @Override
    public void quack() {
        System.out.println("Quack!");
    }
}
class SilentQuack implements Quackable{

    @Override
    public void quack() {
        System.out.println("...");
    }
}
class MallardDuck extends Duck{
    public MallardDuck(){
        quackBehaviour = new Quack();
        flyBehaviour = new FlyWithWings();
    }

    @Override
    void display() {

        // it looks like a Mallard duck
    }
}

如果我想接受鸭子这种方法作为怪胎(与其他动物一起):

class Lake{
    ArrayList<Quackable> quackingAnimals;
    void addQuackingAnimal(Quackable animal){
        quackingAnimals.add(animal);
    }
    void displayQuackables(){
        //...
    }
}

解决方案1:

class MallardDuck extends Duck implements Quackable {
    public MallardDuck(){
        quackBehaviour = new Quack();
        flyBehaviour = new FlyWithWings();
    }

    @Override
    void display() {

        // it looks like a Mallard duck
    }

    @Override
    public void quack() {
        super.quack();
    }
}

解决方案2:

abstract class Duck implements Quackable{
    protected Flyiable flyBehaviour;
    protected Quackable quackBehaviour;
    public void quack(){
        quackBehaviour.quack();
    }
    void performFly(){
        flyBehaviour.fly();
    }
    void swim(){
        // swimming implementation
    }
    abstract void display();
}
wyyhbhjk

wyyhbhjk1#

[就你的问题而言,我更倾向于使用“代表”一词,而不是“行为”,因为我个人认为它更能传达这一概念。]
你的界面 Quackable 意思是“能嘎嘎叫的东西”。
甚至是原作 Duck 抽象类有那个方法,所以它已经遵循那个接口,但您“忘记”了声明那个事实。在一个始终如一的世界里,你应该 Duck 实施 Quackable 从一开始。
关于has和is:
全部 Ducks 吃点吧 quack() 方法,所以它们是有效的 Quackable (意思是“能嘎嘎叫的东西”)。不管他们如何决定他们的quack()实现,使用继承的委托方法,通过提供不同的delegete/行为修改继承的版本,或者重写方法。
事实上他们有 quack() 能力将他们定义为 Quackable .
你的鸭子子类也有一个 Quackable 把它当作一个代表,把真正的夸夸其谈推迟到其他一些“行为”的例子(比如政客们自己不发表意见,而是有一个发言人)。
所以,上课没什么不对的 Quackable 还有 Quackable 同时。在现实世界中,我们都是活生生的动物,我们中的许多人把活生生的动物当作宠物。
关于行为对象的一点意见:
尽管这种模式很有用,但要注意,您失去了使 quack() 行为取决于鸭子的状态(例如,在水上或空气中的声音不同)。

zu0ti5jz

zu0ti5jz2#

这是因为 Duck 类不实现 quack 方法从 Quackable 接口。虽然它有一个 quack 具有相同签名的方法,它与接口中声明的方法不同。
我不明白,为什么解决方案2(使 Duck 类实现 Quackable 接口)将是不合逻辑的-它确实公开了用于嘎嘎叫的公共方法,因此它的所有后代都将 quack 无论如何(但是不同的 quack 是在 Quackable 接口)。在我看来(仅此而已) Duck 类应该实现 Quackable .
如果(对你来说)不是全部
Ducks quack 那么,合理的做法是 Duck 不能被当作 Quackable 行为,因此无法将其添加到 Quackable 物体。在这种情况下(在我看来),您可以创建另一个抽象类来扩展 Duck 实施 Quackable 接口(如 QuackingDuck )在这种情况下(我认为)你应该 quack 方法来自 Duck 类-不是全部
Ducks quack .
我希望它能回答你的问题。综上所述:
这个 quack 方法来自 Duck 不是执行 quack 方法来自 Quackable 接口(例如javascript)
在当前的实施中
Ducks quack ,只有他们的 quacking 行为(实现)是不同的(在 SilentDuck -它还在 quacks )

wn9m85ua

wn9m85ua3#

在超类和接口中都有相同的方法。这个 quack() mallardduck类中的方法一次做两件事:
覆盖 quack() 在超类鸭子里
实施 quack() 在quackable界面中。
解决方案2帮助您避免这种情况。

相关问题