1

I am stuck at a problem. My Problem goes like this. I have a superclass Animal and two subclasses Human And Bird. I have a fly method in my super class Animal which will provide an implementation for both the class Human and Bird based on the Flyable Interface.

My Animal class looks like this.

public class`Animal{

    public Flyable flyable;

    public void fly()
    {
        flyable.fly();
    } 

 } 

Human Class looks like this

class Human extends Animal {

  Flyable flyable;

  public Human()
  {
   flyable = new CantFly();
  }

}

Bird class looks like this

class Bird extends Animal {

      Flyable flyable;

      public Bird()
      {
       flyable = new FlyHigh();
      }

    }

Interfaces are below

public interface Flyable {
   public void fly();
}

public class CantFly implements Flyable{

    @Override
    public void fly()
    {
    Sysout("cant fly");
    }

When I call

Animal me = new Human();
me.fly();

It gives me NullPointerException

What I m missing here ?.
I was assuming. Since I'm calling new Human() it initializes the Flyable interface in superclass Animal. Am I wrong?

I have solved this problem by changing the design of the method.
fly(Flyable flyable).So I don't want that design solution. I remember facing this problem when I was implementing a search algorithm for an app which will provide a list of result but list item will have different
UI,
https call to different End URLs,
Parsing JSON,
Mapping to Different POJO classes.
Sadly I had to solve that problem with an alternate approach which I have mentioned.

Chetan chadha
  • 558
  • 1
  • 4
  • 19
Rohit Singh
  • 16,950
  • 7
  • 90
  • 88
  • Why do you have the `flyable` field in the parent ___and___ the sub-classes? What sense should the duplication make? – Tom Aug 12 '17 at 09:34
  • In superclass to call the method of Flyable interface . And in subclass to initialize the flyable . Do you see this as wrong approach ? – Rohit Singh Aug 12 '17 at 09:37
  • Yes, that's wrong. If you need the field in the parent class, then pass the initialization to that class (e.g. `super(new CantFly());`). – Tom Aug 12 '17 at 09:39
  • But my SuperClass does not have any parameter in constructor. – Rohit Singh Aug 12 '17 at 09:54
  • And i think super(something) approach will fail when your super class is an Abstract class – Rohit Singh Aug 12 '17 at 09:56

1 Answers1

8

Human inherits from Animal, so all its fields are implicitly "copied" from Animal. Therefore, you don't need to redeclare flyable again in Human and Bird.

But you did. This causes the new flyable fields in the subclasses to hide the original field declared in Animal. As a consequence, when you do:

flyable = new CantFly();

in Human, you are assigning a value to the flyable in Human, not the flyable in Animal.

Then you did this:

Animal me = new Human();
me.fly();

fly in Animal uses the field flyable that is declared in Animal class, which has not been assigned yet (you only assigned the flyable in Human)! An NPE occurs as a result.

To fix this, simply remove all the flyable fields in the subclasses of Animal. This way there is only one flyable field.

Note

I think this design a little strange. Human can't fly, so it shouldn't really have a flyable field. In fact, nothing should have a flyable field. Among these 3 classes, only Bird should implement Flyable.

Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • Even Superclass should not have Flyable interface are u suggesting ? – Rohit Singh Aug 12 '17 at 09:49
  • @RohitSingh `Animal` shouldn't implement `Flyable` because not all animals can fly. – Sweeper Aug 12 '17 at 09:50
  • But what if in future i decide to introduce a class FlyWithJetPack which will implements Flyable interface . ? – Rohit Singh Aug 12 '17 at 09:53
  • 1
    You seem to have misunderstood the idea of interface implementation. You don't make lots of concrete classes like `FlyHigh` or `CantFly` and have their instances as fields of `Human` and `Bird`. `Bird` should _directly_ implement `Flyable`. `Human` should have a field called `jetpack` that is of type `Jetpack`. And `Jetpack` should implement `Flyable`. There is no need for a `FlyWithJetpack` class. @RohitSingh – Sweeper Aug 12 '17 at 09:57