Reputation: 693
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();
}
}
Upvotes: 1
Views: 58
Reputation: 11226
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.
Upvotes: 1
Reputation: 774
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();
}
}
Upvotes: 1
Reputation: 242786
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);
}
...
}
Upvotes: 2
Reputation: 206936
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();
}
}
Upvotes: 1