Suppose I have 2 classes ........A Class is base class and class B is derived class and if i create a reference such as : A a=new B(); does it mean that reference a points to object of B Class ? If yes than how am i able to call overridden methods of A in B and not other methods of B ? thank you in advance
class A {
m1() {
}
}
class B extends A {
m1() {
}
m2() {
}
}
A a=new B();
a.m1(); //it will call overridden m1() in B
a.m2(); //it doesnt work if reference "a" points to object of B than why doesnt it call m2 method ?
Animal a=new Dog(); // Animal is parent - class, Dog is a child
means, you have an animal reference pointing to a Dog Object. So, only the methods which are declared in the parent class (Animal) can be called using a parent- class reference.
In your case, m2() is not defined in Class A, it is only defined in class B so, using a reference of A, you can't call m2()
If yes than how am i able to call overridden methods of A in B and not other methods of B
Because the reference is of type A. The compiler can only enforce calling the methods from this type.
Related
Hello everyone,
I am very surprise to see the following program's output:
class A{
int f() {return 0;}
int g() {return 3;}
}
class B extends A{
int f() {return 1;}
int g() {return f();}
}
class C extends B {
int f() {return 2;}
}
public class Test {
public static void main(String args[]){
A ref1 = new C();
B ref2 = (B)ref1;
System.out.println(ref2.g());
}
}
Please help me to explain the code.
You are creating an instance of C and assigning it to the ref1 with type A. Further you are declaring a variable ref2 of type B which get assigned the value of ref1. The value of ref1 is still an instance of C even if you are viewing it by the type of class A.
Calling ref2.g() executes the method g() on the instance of the variable ref2. This is still the one and only created instance of C. Looking on it by the type of class B doesn't change the implementation of the instance the variable ref2 is referring to.
Let us extend class C by a method int h() { return 5; }. Using ref2 you cannot call method h() because the type of the variable is B. But h() is still present on the instance ref2 is referring to. If you extend the main method by
C ref3 = (C) ref2;
System.out.println(ref3.h());
this will output 5. But assigning the value of ref2 to ref3 and calling on it h() implies that the value of ref2 and ref3 (and ref1) is the same.
System.out.println(ref2 == ref3);
This outputs true. So both variables refer to the same object, the instance of C.
I will try to explain by steps:
Reference ref1 points to the instance of the class C.
Reference ref2 points to the same instance of the class C. No matter that it was done with explicit typecast, the instance in the heap still has the type C. Again:
ref2 has the type B;
object instance that ref2 is pointed to has the type C.
When we call to ref2.g(), JVM actually try to find method g() in class C (because object instance in heap has the type C, as was stated above). Because there is no method g() in class C, JVM moves to the parent class B, finds method g() in it, and calls it.
Call to method g() in class B leads to method f(). JVM again try to find that method initially in class C, finds it and return value 2.
This code represents overriding. And in overriding at runtime the jvm decides that which method to call (also called late binding).
Now come to code, the class C has the overridden method f() and in the code you have type-casted the reference of class A (ref1) to class B and called to g() method, so at runtime the jvm will call g() method of class B and ref2 is a reference of class B, which is pointing to class C object, so at runtime the f() method of class C has binded and it will call f() method of class C.
This question already has answers here:
A Base Class pointer can point to a derived class object. Why is the vice-versa not true?
(13 answers)
Closed 7 years ago.
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?
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();
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
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.
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.
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.
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!
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.
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.
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
}
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();
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.
object a2 is of type A but references an object of class C. So, a2 should be able to access m3(). But, why is it not happening? If m3() method had been defined in class A, then the code would run fine
class A {
int var = 7;
void m1() {
System.out.println("A's m1 ,");
}
void m2() {
System.out.println("A's m2 ,");
}
}
class B extends A {
void m1() {
System.out.println("B's m1 ,");
}
}
class C extends B {
void m3() {
System.out.println("c's m3 ," + (var + 6));
}
}
class Mixed {
public static void main(String[] args) {
A a = new A();
B b = new B();
C c = new C();
A a2 = new C();
a2.m1();
a2.m2();
a2.m3();
}
}
A a2=new C();
That means you can access only the members of Class A and implementations of Class C, if any overridden.
Now m3 is not a member of A. Clear ?
When you write this line
A a2=new C();
a2 will only ever be able to access methods defined in Class A.
Even though a2 refers to an instance of Class C, it cannot invoke methods defined only in C.
However, if you had the following:
class A {
void m3() {
System.out.println("in A");
}
}
class C extends A {
void m3() {
System.out.println("in C");
}
}
...
A a2 = new C();
a2.m3();
would output
in C
In this case, the m3() method is being overridden and the method invoked will be determined by the type of the instance which a2 refers to (i.e. C).
I would take a look at the Java tutorials here: http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html
If you use a reference of the parent / superclass and try to invoke a method on the subclass, then that method should be defined in the parent / superclass. i.e, what methods you can call on the object(rhs) depends on the lhs (reference type).
You see the subclass C as an instance of A because an A does not have the function m3 that a C has.
A a2 = new C();
So here, you can access only the methods in C that are inherited from A. You basically see it as an A. If you wanted to call the methods in C, you would have to cast it to C, so you'd have to do something like this:
if(a2 instanceof C)
{
C castedA2 = (C)a2;
castedA2.m3();
}
Compiler checks reference of object which is invoking a method...
In your case A a2=... is what compiler can see, and it finds that there is no m3() method defined in A class. Hence code will not compile.
Note that,
While invoking method at runtime, JVM refers the object referenced by the Reference. In your case Reference of class A is referring Object of class C.
Read more at : Polymorphism in Java
Ok.. So,
When you have a hierarchy of classes such as
public class A {...}
and,
public class B extends A {...}
...When you create objects, what is the difference between:
A object = new A();
A object = new B();
B object = new B();
Thank you for your time.
public class A
{
public void methodA(){}
}
public class B extends A
{
public void methodB(){}
}
I hope this can demonstrate the difference.
A obj = new A();
a.methodA(); //works
A obj = new B();
obj.methodA(); //works
obj.methodB(); //doesn't work
((B)obj).methodB(); //works
B obj = new B();
obj.methodA(); //works
obj.methodB(); //works
A object = new A();
You are creating an A instance in a reference of type A. You may can access only A methods/properties and parents methods/properties.
A object = new B();
You are creating B instance in a reference of type A. In this way object could behave in a polymorphic way, for example if you make object.method() and method is overriden in B then it will call this override method. You have to take care in not to break the Liskov Substitution Principle. You may can access only A methods/properties and parents methods/properties. This is the preferred way when you only need supertype contract.
B object = new B();
You are creating a B instance in a reference variable of type B. You may can access only B methods/properties and parents methods/properties.
A line like
A var = new B();
is kind of a shorthand for two separate steps.
A var; // (1) Make a variable of TYPE A.
var = new B(); // (2) Make an object of CLASS B, that from now on may be
// referred to by the variable var.
So a variable has a TYPE, and an object has a CLASS. Often they match up. The type of a variable is often actually a class, although not necessarily. It's important to understand the difference between the type of a variable, and the class of the object that the variable refers to.
An object typically belongs to more than one class. If class B extends class A, that means that all objects of class B are also objects of class A. And all objects of any class at all are also objects of class Object. In other words, when we say that an object is a B, that's more specific than saying it's an A. Just like when we say that Yogi is a bear, that's more specific than saying Yogi is an animal, because all bears are animals.
So a variable of type A can indeed refer to an object of class B, if A is a class that B extends. But if you've got a variable of type A, you can't use it to do things that are specific to objects of type B. For example, suppose class A has a method called display() and class B has a method called explain(). The compiler will let you call display() on a variable of type A, but it won't let you call explain(). If it did, it would be risking trying to call explain() on an object that's not actually a B, which would fail.
So whenever there are methods that class B defines, you'll need a variable of type B in order to be able to call them. Of course, you can also use that same variable to call the methods that are defined in class A. In a sense then, if class B extends class A, then a variable of type B is more powerful than a variable of type A - you can do more stuff with it.
So the question arises - why would I ever want to write
A var = new B();
when a variable of type B would be more powerful than var in this example?
The short answer is that it communicates to people looking at the code. It says, "yes, I know this variable refers to a B, but I actually only intend to use the methods provided by class A. This can actually be helpful to someone trying to understand your code, or to maintain it.
There are also cases where it can make a real difference to method calls involving that variable. Suppose there's another class C, which has two methods with the same name but slightly different signatures, like this.
public class C {
public void process(A arg){
// Do some stuff
}
public void process(B arg){
// Do some other stuff
}
}
In this particular case, the version of process that gets called depends on the type of the variable, not the class of the object. So if you write
C processor = new C();
A var = new B();
processor.process(var);
this will call the first version of process - the one with A in the signature. Because of the type of the variable. But if you write
C processor = new C();
B var = new B();
processor.process(var);
this will call the second version of process - the one with B in the signature.
A object = new A();
object of type A (you can access fields or method from A)
A object = new B();
object of type A (you cannot access fields or method from B, only from A)
B object = new B();
object of type B (you can access fields or method from A and B)
A object1 = new A();
A object2 = new B();
B object3 = new B();
object1 is declared as a reference to an A object. Since class B extends class A, it could be set to either or (new A() or new B() would be valid).
object2 is declared as a reference to an A object, but is actually a B object. Say the B class has a method called eatFood(). If you tried to access that method with object2.eatFood(), the compiler would throw an error because the eatFood method is only in the B class. Even though the object is actually a B object, the compiler thinks it is an A object due to the type declaration. To access the eatFood method, you would have to typecast it: ((B)object2).eatFood().
object3 is simply a reference to a B object, and in reality IS a B object. It could access A methods as well as B methods.
A object = new B();
This declares that object will refer to an object of class A or any of its subclasses (when it isn't null). The compiler will treat it as an object of type A, so you can only access methods and fields that are declared for A (or one of its superclasses). It also means that you can later assign it to any other object that is of class A or a subclass:
A object1 = new B();
B object2 = new B();
// reassign later
object1 = new A(); // legal
object2 = new A(); // ILLEGAL
class C extends A { ... }
object1 = new C(); // legal
object2 = new C(); // ILLEGAL
So the initial declaration declares object as having type A. But its initial value is an object of type B, which is OK because B is a subclass of A.
That should explain the difference between your second and third examples. The difference between the first and second is simply that (at run time) the first creates a new object of type A and the second creates a new object of type B.
class A{
int a=10;
public void show(){
System.out.println("Show A: "+a);
}
}
class B extends A{
public int b=20;
public void show(){
System.out.println("Show B: "+b);
}
}
public class DynamicMethodDispatch {
public static void main(String[] args) {
A aObj = new A();
aObj.show(); //output - 10
B bObj = new B();
bObj.show(); //output - 20
aObj = bObj; //assigning the B obj to A..
aObj.show(); //output - 20
aObj = new B();
aObj.show(); //output - 20
System.out.println(bObj.b); //output - 20
//System.out.println(aObj.b); //It is giving error
}
}
In the above program i'm getting Error wen i try invoking aObj.b.
1.why i'm not able to acess that variable through the aObj though it is refering to class B??
2. why i'm able to acess the method show()?
You have to distinguish between the static type of aObj and the runtime type of aObj.
Code such as
A aObj = new B();
results in an aObj variable with static type A and runtime type B.
The compiler will only bother too look at the static type when deciding what to allow or not.
To your questions:
1.why i'm not able to acess that variable through the aObj though it is refering to class B??
Because there is (in general) no way for the compiler to know that aObj will refer to a B object at runtime, only that it will refer to some form of A object. Since .b is not available on all A objects, so the compiler will think "better safe than sorry" and disallow it.
2.why i'm able to acess the method show()?
Because this method is available in all A objects (if it's not declared in the subclass, it is still inherited from A).
aObj is a local variable of type A. A has no member called b, that's only in your subclass B. If you want to use b, you need to declare a variable of type B, but of course you can only assign it instances of B (or subclasses if there are any).
A declares a method show(), but you override the implementation in your subclass B.
This behavior is known as virtual method invocation, and it is an important aspect of polymorphism in Java. You should have a look at this tutorial.
class A{ // class A has variable a and method show();
int a=10;
public void show(){
System.out.println("Show A: "+a);
}
}
class B extends A{ //class B inherits variables and methods of A.
// so class B has variable a, b and show(). Also, show is overridden by class B.
public int b=20;
public void show(){
System.out.println("Show B: "+b);
}
}
since A doesn't have variable b inside it, even when u are passing B to A, you still have A object which does not have variable b inside it. So, trying to access b will give you compile time error.
in case of show(), A and B both have this method, so what you are doing here is actually overriding it at runtime. This is nothing but Polymorphism. So since A already has method show(), and it is overridden later by B,
A a = new B();
a.show();
this will run the show() method of B at runtime.
Methods and fields have different polymorphic behaviour.
The method that will be called is the method of the run time type of the instance
aObj=new B(); //new B()
The field that will be called is the field of the type of reference that you declared
A aObj = new A(); // A aObj
The following would work even is there was no show() method in A.
aObj = new B();
aObj.show(); //calls B's show()