How does a polymorphic instance select its methods? - java

I have problems understanding the behaviour of this piece of code.
a is defined as an A, c is defined as a C.
Then, at the end of the public class, a = c.
When a calls the display() method it reaches the C version of it.
But when a calls the f() it only reaches the A version, despite the fact that the first arguments (byte and long) are more compliant with long than float.
It's an exercice from a book, but explanation is scarce, or inexistent.
class A{
public void display(){
System.out.println("I am an A ");
}
public void f(double x){
System.out.println("A.f(double = " + x + ") ");
}
}
class C extends A{
public void display(){
System.out.println("I am a C ");}
public void f(long q){
System.out.println("C.f(long = " + q + ") ");}
}
public class PolySurStack{
public static void main(String Args[]){
byte bb =1; long q = 4; float x = 5.f;
System.out.println(" ** A **");
A a = new A(); a.display();
a.f(bb); a.f(x);
System.out.println();
System.out.println(" ** C **");
C c = new C(); c.display();
c.f(bb); c.f(q); c.f(x);
System.out.println();
a = c; a.display();
a.f(bb); a.f(q); a.f(x);
}
}

When you call a.f(bb) or a.f(q) or a.f(x), the only method signatures the compiler can choose from are those defined in class A (or any super class of A), since a is a reference variable of type A.
Therefore, only public void f(double x) is considered. In order for public void f(long q) to be a candidate for overload resolution, you'd have to cast a to type C before calling f(), since only class C defines a method with that signature.
The important thing to understand is that method overloading resolution takes place in compile time. Only the compile time type of the reference variable for which you call the method determines which method signatures are candidates for method overloading resolution, as well as which candidate will be chosen.

I just found this on another forum :
Overloading :(same function name but different signature)
Two or more methods having the same name with different arugment in same class is known as Overloading.
Overloading is used when you want to extend the functionality.
Overloading is known as compile time polymorphism
Overriding :(same function name but same signature)
Two or more methods having the same method name and same arugment in parent class and child class in known as overriding.
Overriding is used when you want to reuse the existing functionlity.
Overriding is known as run time polymorphism
So the answer to my question seems to be that overriding resolution (like for display() )occurs at run time (here after a = c) while overloading resolution (like for f() ) occurs at compilation time, when a is Still an A.
I think.
I also found this page : https://beginnersbook.com/2013/04/runtime-compile-time-polymorphism/
to be clear and highly relevant to this topic.

The method selected by the compiler depends on the declared type, not on the runtime type.
The first series that declares as variable A can only invoke A methods (whatever the runtime type instantiated as A derives only of Object) :
A a = new A();
a.f(bb); a.f(x);
For the second series, the compiler binds the methods with the most specific parameter matching to the invocation since C is a A and so the compiler can bind any public methods of these here :
C c = new C();
c.f(bb); c.f(q); c.f(x);
But in the last chunk of code that probably questions yourself, a refers to C as runtime object but to A as declared type :
A a = new A();
// ...
a = c;
a.f(bb); a.f(q); a.f(x);
So only methods defined in A may be invoked.

I'll try to clarify the answer of #eran a bit so you can understand it.
A subclass has all the methods of its superclass, and then perhaps some more in addition to them. You have a variable of type A, in which you store an object of type C. C has all the methods that are defined in class A, and also an additional method that is f(long q). A is unaware of this new method, so since you store the object in a variable of A, you can't call f(long q).
You can however call display() because it is defined in A, but it will still be the C object that executes it.

Related

Java casting, overide and polymorphism

In the following example, I reckon it's something about run time polymorphism, but I can't figure out why y.m1(x) prints out A. My understanding is that y.m1() calls the m1()method in class B, because y contains an object of B. Since x is passed to it as a parameter, and it belongs to the class A which is wider than B, won't it lead to a run-time error? Plus how come z.m1(y) prints out A too?
Many thanks in advance!
class A {
public void m1(A a) {
System.out.println("A");
}
}
class B extends A {
public void m1(B b) {
System.out.println("B");
}
}
class D2 {
public static void main(String[] args) {
A x = new A();
A y = new B();
B z = new B();
}
}
B's m1 does not override A's m1 method, as it does not take the same parameter. So B class consist of two overloaded m1 methods, one taking an A object, the other taking a B object.
Only static polymorphism can be used here, that's why you can see this behavior.
The dynamic type of an object (the type used in the new) is it's actual runtime type: it defines the actual methods that are present for an object.
The static type of an object reference (a variable) is a compile-time type: it defines, or rather declares, which methods can be called on the object the variable references.
Because the parameter type of both the dynamic type and the static type are different, we dynamic type doesn't override the method, but overloads it.
If the parameter types would have been the same, the output would be B...

Dynamic binding in java?

I have a little confusion with Dynamic Binding in java.
Here is a program, I want to know that, is there dynamic binding occurs or something else.
What dynamic binding actually is?
class A {
int a;
public A() {
a = 9;
}
public void show() {
System.out.print("show in A ; ");
System.out.println("a : " + a);
}
}
public class B extends A {
public B() {
a = 8;
}
public void show() {
System.out.print("show in B ; ");
System.out.println("a : " + a);
}
public static void main(String[] args) {
B p = new B();
p.show();
A q = new B();
q.show();
}
}
It's here
A q = new B();
q.show();
Compiler uses virtual call instructions (invokeVirtual or invokeInterface) for methods which can be overriden (they cannot be static or private). In this code JVM detects that A.show is virtual and checks the actual type of q. Since it is B it calls B.show. If it were static JVM would call A.show and we would see
show in A
I guess I confused you previously.
Dynamic (or late) binding is how polymorphism is implemented in Java. It occurs any time an instance method is invoked.
In your example, we are interested in the occurrences here
p.show();
and here
q.show();
At compilation time, the static type of the variable will be checked to see if the method show() is accessible, failing if it is not.
At runtime (dynamic), the run time (dynamic) type of the object will be checked to find an implementation of the method. If one is found, it is used, if not, the JVM keeps looking up the inheritance hierarchy.
For example
A q = new B();
q.show();
at run time, q is of type B and B overrides show() so B#show() is invoked.
In your answer I had commented on, the overriden method did not play a part. It was more a question of constructor execution order.
The method show() invoked in the below lines
A q = new B();
q.show();
The target object of the show method is determined at runtime.
you can change it in your main method to implement polymorphism or dynamic binding:
public static void main(String[] args) {
A a = new A();
a.show();
a = new B();
a.show();
}
as you can tell that even the reference is never changed A a but what it refer is changed, as different instance it point to, difference behavior will be done!
This is so called polymorphism.
Much powerful polymorphism, after using reflect in java will indulge you! have fun!
- Binding is act of method call identifying and calling its method body.
- Java only supports Dynamic Binding, except few exception cases.
- The compiler can't understand which method call to be associated with which method body... so its the responsibility of the method call to associated itself to its appropriate method body.
- Its very important to know that Fields (Instance Variables) are NOT POLYMORPHIC IN NATURE.
In your case the Dynamic binding is here:
A q = new B();
q.show();

Is this Overloading, methods with same name in different classes and different signature?

If I have the following code in Java:
class A {
public int add(int a , int b) {
return (a+b);
}
}
class B extends A {
public float add(float a , float b) {
return (a+b);
}
In this particular case the sub-class isn't exactly overriding the base class's add function as they have different signatures and the concept of overloading occurs only if they are in the same scope. So, is the function add(float , float) in the sub-class B treated as an entirely new function and the concept of overloading and overriding is not applicable to it? And does it use 'Static binding' or 'Dynamic Binding'?
Method add in class b is an overload of add in class a. Not an override. An override would just be a different implementation of the original add method.
In brief, yes. To override, you need to replicate the complete method signature, which includes the method name, parameters and return types. From the tutorial
An instance method in a subclass with the same signature (name, plus
the number and the type of its parameters) and return type as an
instance method in the superclass overrides the superclass's method.
You might want to consider the #Override annotation, which will trigger a compiler error if you don't successfully overrride a method.
In this particular instance, it perhaps looks like you don't need overriding so much as some solution including generics. So you could instantiate a class a<Integer> and a similar class a<Float>
In that case you are not overriding the method, since the signatures are different.
But there is overloading in class b, since you have two methods with the same name but different parameters (one if class a, and the other one in class b)
Hope it helps.
There can be a method that is not overridden but overloaded in the subclass. Here the subclass has two add() methods. The version which accepts int arguments(not overridden), and the overloaded method add() which accepts float arguments.
I think in this particular case neither overloading nor overriding occurs, because return type must be same in case overloading and overriding, so neither static binding nor dynamic binding happens in this case.
method overloading is not possible in case of different return type, because compiler can't figure that which method he need to call.
I know it's late answer but i think it's important question need to be answered for beginners.
One key point in overloading is it works in inheritance.
Next is either it's Static binding or Dynamic binding.
It is Static Binding So, why?
Static Binding
Static binding in Java occurs during Compile time.
private, final and static methods and variables uses static binding and bonded by compiler.
Static binding uses Type (class in Java) information for binding.
Dynamic Binding
Dynamic binding occurs during Runtime.
Dynamic methods bonded during runtime based upon runtime object.
Dynamic binding uses Object to resolve binding.
But the important part is here
Overloaded methods are bonded using static binding while overridden methods are bonded using dynamic binding at runtime.
Java compiler determines correct version of the overloaded method to be executed at compile time based upon the type of argument used to call the method and parameters of the overloaded methods of both these classes receive the values of arguments used in call and executes the overloaded method.
B a=new B();
a.add(4, 5);
a.add(4.0f, 5.0f);
So if you will create reference of type B then it will search for proper argument type
and for above code it will execute both methods.
A a=new B();
a.add(4, 5);
a.add(4.0f, 5.0f);
but for above code it will give compile time error for float arguments.
Hope it clears all doubts.
First things first
Is it method overriding ?
No , since to override a method you need to replicate the complete method signature as pointed out in Brian Agnew's answer and as I explain below.
Is it overloading ?
Yes , Method "add" has an overloaded implementation in Class B.
Consider the following code:
class C{
public static void main(String args[]){
B a = new B();
a.add(2 , 3);
a.add(2.0 , 3.0);
}
}
class A {
public int add(int a , int b) {
System.out.print("INT ");
return a + b;
}
}
class B extends A {
public double add(double a , double b) {
System.out.print("Double ");
return a + b;
}
}
OUTPUT : INT Double
So , the method in Class B in your code overloads the add method that it inherits from its parent
Does it use Static Binding or Dynamic Binding ?
This is what makes me conclude that OP is confused.It is static binding because it is a overloaded function. The only way to think of dynamic binding would have been in below scenario
class C{
public static void main(String args[]){
A a = new B();
a.add(2.0 , 3.0);
}
}
class A {
public int add(int a , int b) {
System.out.println("A : INT");
return a + b;
}
}
class B extends A {
public int add(int a , int b) {
System.out.println("B : INT");
return a + b;
}
public double add(double a , double b) {
System.out.println("Double");
return a + b;
}
}
Output : B : INT
Here , the parent class A has a contract that says , "I have an add behaviour for ints" . class B inherits this add behaviour and makes it more specific and at the same time also provides a new behaviour where it can add doubles.
But class A has "no knowledge of this behaviour".
So an object of class A "cannot" add doubles. To do that you need a more specific type of A object i.e. a B object.
The method add() in class A is also available to class B by inheritance, therefore the method is overloaded in class by changing the data type from int, int to float, float.
The concept of Overloading comes in play if and only if the functions are in the same scope or class.
cz if this is the case of method overloading then for same method signature or same argument type the compiler gets confuse and must give compile time error .
but in the above program in class B if you pass the same argument in same order then according to overloading it must give error but it is not happening u can check it i already have.
It is the case of inheritance where through object reference if you call any method then the compiler will check it in child class ,if its not there then it will look into parent class that the above program is all about.
hope this is helpfull.

Hiding vs. overloading in C++/Java?

Here's what i remembered:
In C++, if derived class defines a member function with the same name, but different signature (parameter etc) than the base class, it'll 'hide' the corresponding member function in base. e.g.
class Base {
public:
void virtual f(double x);
};
class Derived : public Base {
public:
void f(char c);
};
int main()
{
Derived* d = new Derived();
Base* b = d;
b->f(65.3); // call f(double x)
d->f(65.3); // call f(char c)
delete d;
return 0;
}
correct me if i am wrong, but i think in C++ by saying 'hide', it also means Derived class can not see 'f(double x)', or in other words, Derived do not have 'f(double x)' as its inherited member function from Base, correct?
In Java tutorial, 'hide' actually means something else (for static class method), whereas for instance method, you can overload the method inherited from base. Looking at this example: Using inherited overloaded methods
public class ClassA {
public void method(Number n) {
System.out.println("ClassA: " + n + " " + n.getClass());
}
}
public class ClassB extends ClassA {
public void method(Integer d) {
System.out.println("ClassB: " + d + " " + d.getClass());
}
}
ClassA a = new ClassB();
a.method(3);
In C++ type of thinking, i would get the same result that 'method(Number n)' from Class A is called, based on 'dynamic binding' and 'hiding' idea in C++, but:
I am still not sure how to explain it in Java. The link itself explains using 'method signature is chosen at compile time' and 'it is actually calling from Class B'; but in C++ thinking, the former is OK, but i do not think it's calling from Class B, it should be calling from Class A, right?
In Using inherited overloaded methods and Java tutorial, 'Class B' is allowed to overload function from 'Class A', and 'Class B' actually can see both 'method(Number n)' and 'method(Integer d)'. So C++ and Java are treating overloading differently, right? And why is that? Say in the C++ example, if Derived also allow overloading, 'd->f(65.3)' would call 'f(double x)', not 'f(char c)'.
Thanks,
In C++ every thing is static for non-virtual functions, so for non-virtual functions you don't have dynamic-binding. And hiding do not remove function from inheritance. It's something like this:
When you define method M as: void M(int) then compiler implement a function internally name Base::M as void Base::M( Base* this, int ). Now this function is implemented somewhere in code and can't removed and you can call it as long as you be able to provide a this (actually you can call it without even having this). So in Child I can call Base::M(0); and C++ convert this from Child* to Base* and call M. When you define a function with its name correspond to the name of base class you tell the compiler that I prefer to use that name in my class for a new method or property! But you don't remove any thing and you can use using to bring old definition of M to Child:
struct Base {
void f( int ) {}
};
struct Child : Base {
void f( char* ) {}
using Base::f; // Bring Base::f to this class, so I have f(char*), f(int)
};
And beside that you can call f(int) without even use of using.
// In the Child class
void test() {
Base::f('c'); // Call Base::f(char)
}
// Outside of class
Child c;
((Base*)&c)->f('1');
This is not how I would expect C++ to behave. Rather than hiding the base class method, I would expect the subclass to simply overload the method because the parameters are different. Thus, the compiler will know which method to use when you call b->f() because there's only one available, but it has to work out which one to use when you call d->f() based in your parameter type. If it can't then at compile time you will be forced to use a cast. With your example it should recognise the decimal point and use double instead if char.

Why does sysout(upper class) invoke toString of lower class after assigning lower class to upper class?

I have two classes A and B while B is a subtype of A:
public class A {
private String stringVar;
public A() {
stringVar = "";
}
public String getStringVar() {
return stringVar;
}
public void setStringVar(String str) {
this.stringVar = str;
}
#Override
public String toString() {
return getStringVar();
}
}
Class B:
public class B extends A {
private int intVar;
public B() {
intVar = 0;
}
public int getIntVar() {
return intVar;
}
public void setIntVar(int intVar) {
this.intVar = intVar;
}
#Override
public String toString() {
return super.toString() + " " + getIntVar();
}
}
As you can see in the following main method I assign the b to a. Now "a" can't invoke b's methods which is clear, because I'm using an instance of type A now. But it behaves like a B when toString is invoked. Curious, I would have expected toString of a. Why is this so?
public class Main {
public static void main(String[] args) {
A a = new A();
B b = new B();
b.setIntVar(200);
b.setStringVar("foo");
a = b;
System.out.println(a);
}
}
Because a points to the implementation of B.
And is declared as A.
So behavior of B. And methods visible of A.
To use B methods do like this
((B) a).getIntVar();
Think of it like this
Object o = new FancyObject();
When compiling this only Objects methods will be accepted even though it's a FancyObjcet with lots of methods.
To use the methods of FancyObject on o do like this.
Object o = new FancyObject();
(FancyObject o).fancyMethod();
Quote "because I'm using an instance of type A now" you are still using an instance of type B. You can see it like you have upcasted b but it's the same instance.
Picture cross linked from another site with credits in the picture, if this is against the rules then somebody is free to edit this part of my answer.
This is nature of inheritance / polymorphism and overriding methods.
Overrided methods will be determined in runtime based on objects real type and not based on reference type.
Therefore a.toString() is actually b.toString() because it is determined in runtime.
http://download.oracle.com/javase/tutorial/java/IandI/override.html
The concept you need to understand is the difference between References and Objects.
a is a reference (a local variable in this case) that points first to an Object of type A and then to an Object of type B.
The compiler knows that it must be of type A (or a subtype thereof), so it can safely call all methods A defines, but they will be called on the actual Object, not on the original Type of a.
This is polymorphism: The object that a holds has static type A, but it is still an Object of dynamic type B. Dynamic dispatch therefore chooses the overridden toString() defined in B.
That's exactly how Java's runtime polymorphism works. All that matters is the actual type at runtime. What you have done is take a reference to an A and point it at an instance of B. You have changed the type of the thing that a points to.
Try
a = (A)b;
No, B Overrides the toString method of A, so if an object is an instance of B, when you call its toString method, you get whatever method that instance has. In general, if you have an object and call its methods, the method called is the one that is in the instance, not in the variable type. The only exception is static methods.
In C++, this is not the case. The method called is the one of the variable type, if one exists, unless you explicitly select the above described behavior by making a method virtual.
That is called runtime polymorphism in OOP.

Categories

Resources