2020-11-27

Java Interface does not take into consideration method implementation from the super class

The following example with ducks, is based on the Head First design patterns book.

I have a game with different types of ducks. There is a super class Duck and it has two behaviours: fly and quack, which are stored in fields. The concrete classes decide (in the constructor) which behaviour a concrete breed has (see MalardDuck class).

I realised I want my ducks to not only have type Duck but also Quackable (so that I can have methods that accept only quackables - assuming that there are other types that quack - see Lake class). When I implement the interface in MallardDuck, the compiler complains that the class does not have the method quack although it is defined in its superclass - Duck class.

Now I could think of two solutions:

  1. Overwrite a method quack by just calling the method from the superclass: super.quack() <- but that seems unnecessary (in theory) - a child class has a direct access to superclass's public methods, so why the interface Quackable even complains...?
  2. Make Duck implement the Quackable -> this is rather illogical cause some Ducks don't Quack (their quackBehaviour is implemented with SiletnQuack class).

However in both solutions the duck:

  • HAS A quackable behaviour, AND
  • IS A quackable

Isn't that fundamentally wrong? What am I missing?

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
    }
}

What if I want to accept ducks to this method as quackables (along with other animals):


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

Solution 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();
    }
}

Solution 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();
}


from Recent Questions - Stack Overflow https://ift.tt/37bIotv
https://ift.tt/eA8V8J

No comments:

Post a Comment