Question

B inherits A while D inherits C. D instances are passed B instances to operate with, but without overriding the variable or creating a new reference D types can't see the bStuff().

class Ryrich_A { 
  public void aStuff() { System.out.println("a-type stuff"); }
}
class Ryrich_B extends Ryrich_A { 
  public void bStuff() { System.out.println("b-type stuff"); }
}

class Ryrich_C { 
  Ryrich_A a; 
  Ryrich_C(Ryrich_A a) { 
    this.a = a; 
  }
}

class Ryrich_D extends Ryrich_C{    
  Ryrich_D(Ryrich_B b) {
    super(b);
  }

  public void doStuff() {
    a.aStuff();
    // a.bStuff();  --problem--
  }

  public static void main(String[] args) {
    new Ryrich_D(new Ryrich_B()).doStuff();
  }
}
Was it helpful?

Solution

If subclasses of C are supposed to work with specific subclasses of A (i.e. D always works with B), you can make C generic:

class C<T extends A> { 
    T a; 
    C(T a) { 
        this.a = a; 
    }
    ...
}

class D extends C<B> {    
    D(B b) {
        super(b);
    }
    ...
}

OTHER TIPS

That is, ofcourse, because the member variable a in class C is of type A and not B.

So, in the method doStuff in class D, you can't call any methods on a that exist only in class B - the method doesn't know that a really refers to a B.

You can only get around this by doing a cast in D's doStuff method (which is not very nice), or by changing the type of a in class C to B.

class D {
    // ...

    public void doStuff() {
        ((B) a).bStuff();
    }
}

If you ovverride the method in class B, I think you get the desired result.

class A { 
    public void doStuff() { System.out.println("a-type stuff"); }
}

class B extends A { 
    public void doStuff() { System.out.println("b-type stuff"); }
}

class C { 
    A a; 
    C(A a) { 
        this.a = a; 
    }
}

class D extends C{
    D(B b) {
        super(b);
    }

    public void doStuff() {
         a.doStuff(); //calls B's doStuff method
    }

    public static void main(String[] args) {
        new D(new B()).doStuff();
    }
}

It cannot see it because a in class C is of Type A.

Here is an example I have seen at a lot of places but it still helps.

class Animal
{
    public void eat(){
        System.out.println("Animal eats something");
    }
    public void organic(){
        System.out.println("Animals are organic");
    }

}
class Dog extends Animal
{
    @Override
    public void eat(){
        System.out.println("Dog eats something");
    }
    public void eat(String food){
        System.out.println("Dog eats +"food);
    }
    public void bark(){
        System.out.println("Dog barks");
    }
}

Animal dog =  new Dog();

dog.eat();                  //Dog eats something

((Animal)dog).eat();        //Dog eats something    

//Still we get Dog's eat(). There is no way you could call eat() method of Animal using this dog.

((Dog)dog).eat("steak");    //Dog eats steak

//To call methods only in the subclass we need to cast it to the Object type

((Dog)dog).bark();          //Dog barks

//Same as above

dog.organic();              //Animals are organic

//With no worries we could call methods in Animal (Reference type)


Animal a = new Animal();
Dog d = (Animal)a;

//compiles but fails at runtime. If the types are in the same Inheritance tree, compiler says OK.

Animal a3 = new Animal();
Dog d1 = (Dog)a3;       

//compiles because compiler sees both Dog and Animal in same tree. But fails during runtime.

Dog d = new Dog();
Animal a1 = d;
Animal a2 = (Animal)d;

//Both compiles and runs fine.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top