-2

This is rather basic question. But I can't understand well the concept of inheritance.

Suppose I have two classes, A and B with both have a test() method that returned 1 and 2 respectively, and B inherited A class. In main method I declare the instance as such;

A a1 = new B();

and call the method a1.test(), it will return 2. This is the concept of polymorphism. But when I have a method test2() in just subclass, I can't call the method using the same instance declaration as above. Why is that happen?

Zerocchi
  • 614
  • 1
  • 8
  • 20

11 Answers11

3

I can't call the method using the same instance declaration as above. Why is that happen?

Because the type of the variable is A, and class A does not have a method test2(). The Java compiler only looks at the type of the variable to check if you can call a method, it does not look at the actual object (which is in this case a B).

This is all easier to understand if you use more concrete and meaningful names for your classes, instead of abstract names such as A and B. Let's call them Animal and Bear instead:

class Animal {
}

class Bear extends Animal {
    public void growl() { ... }
}

class Cat extends Animal {
    public void meow() { ... }
}

Animal a1 = new Bear();
Animal a2 = new Cat();

// Doesn't work, because not every Animal is a Bear, and not all
// animals can growl.
a1.growl();

// You wouldn't expect this to work, because a2 is a Cat.
a2.growl();
Jesper
  • 202,709
  • 46
  • 318
  • 350
1

Because variable type is A, and class A does not have a method test2():

Rather you can use:

A a1 = new B(); // upcasting 
B b1 = (B)a1; // Downcasting a1 to type B
b1.test2(); // now you can call test2 function
Sumit Singh
  • 15,743
  • 6
  • 59
  • 89
1

Because, the left side of your condition determines which method's you can call, and right side determines which methods will be called. So in this case class A does't have test2() method.

Vladyslav Sheruda
  • 1,856
  • 18
  • 26
1

Imagine A = "TV" and B = "HD_TV".

You can say

TV tv = new HD_TV() // HD TV

and

TV tv = new TV() // ordinary TV

because an HD_TV is a TV.

You can say:

tv.show(movie) 

It will show what is on TV, but you will get a better picture with the HDTV.

You cannot say:

tv.showHD(hdMovie) // Compiler error !!!

because in declaring tv as TV, you are saying it might not be an HD TV. Even though you can see that in this case it is, the compiler still respects your declaration that it is just a TV and you can only use methods supported for a TV.

rghome
  • 8,529
  • 8
  • 43
  • 62
0

That is because you are declaring the instance a1 as an A. Because B inherits A, you can call all the functions declared in A and they might have a different meaning if they are overloaded in B, but you do not have any access to B-only things.

You can see the first A as some kind of a header file, if you are familiar with that. It declares what A contains, without looking at how the functions are implemented or what the default vars are of everything in A. As a direct consequence, you can only access everything that is declared to literally be in A.

Cheiron
  • 3,620
  • 4
  • 32
  • 63
0

The left-hand side - A in this case - is the declared type, and it doesn't know about anything specific to child classes. The right-hand side - ´B´ in this case - is the actual type, and this provides the behaviour.

So, this will work because the declared type B knows about methods available in the class B.

B b1 = new B();
b1.test2();

If it was possible to have a1.test2(), that would mean every class would have to know about every child it has - including those in other libraries, when projects are assembled!

Steve Chaloner
  • 8,162
  • 1
  • 22
  • 38
0

When B inherits A class and the reference of A is created with object of B like A a1 = new B();.

On Compile time java compiler looks for method availability in class A.

So it allows calling method test() but not the test2(). As test() method is available in class A but test2() is not available in class A.

You can type cast the object created like ((B)a1).test2(). This will work.

Mandar Pandit
  • 2,171
  • 5
  • 36
  • 58
0

Here a1 object is of type A. a1 is pointing to an object of type B. a1 is a reference of type A to an object of type B.

since a1 is of type A it know only test() which is declared in its class definition already. In case you want to access test2 declared in class B you need to type cast the a1 object back to B

like B b1 = (B)a1

b1.test2() will be accessible.

amith
  • 399
  • 1
  • 2
  • 11
0

This happens because you declare A variable and use B class which is an A. The compiler know it's an A but doesn't know it's a B later in the code. It's easier to use real life objects as example.

For example you have:

class Pet() { 
 method feed();
}

And a

class Dog() extends Pet {
 method feed();
 method bark()
}

If you have a code in another class:

So if you have code :

Pet dogPet=new Dog();

You know it's a dog here because you create the instance and you can use: ((Dog)dogPet).bark(); or just declare the variable as a dog instead of pet.

But if you have a method in another class:

void someMethod(Pet aPet){
  // Here you don't know if the Pet is a dog or not. So you know only that it       
  //can be fed but you don't know if it barks. Even if a Dog is supplied to the method
}
Veselin Davidov
  • 7,031
  • 1
  • 15
  • 23
0

In a1 = new B(), the actual type of the object created is B but you reference it as its supertype so you can call a method that accepts A (polymorphism).

So if a method is overridden in subclass, a1.test() is executing subclass's test().

In order to execute test2() you have to do that: ((B) a1).test2();

Fran Montero
  • 1,679
  • 12
  • 24
0

There is a concept called Up casting and Down casting.Up-casting is casting to a supertype, while downcasting is casting to a subtype. Supercasting is always allowed, but subcasting involves a type check and can throw a ClassCastException.,See the Example Code:

class A{
public int test(){
 return 1;
}
}

class B extends A{

public int test(){
 return 2;
}

public int test2(){
    return 3;
}
}

and

A a1 = new B();
a1.test2();//not possible

Here you can't invoke methods of class B.

moh
  • 1,426
  • 2
  • 16
  • 43