Java virtual function calls - java

From my understanding all function-calls in Java are virtual, and numeral literals have the type int. But why does the Output in the example below differ?
public class A {
public int f(long d) {
return 2;
}
}
public class B extends A {
public int f(int d) {
return 1;
}
}
public class M {
public static void main(String[] args) {
B b = new B();
A ab = b;
System.out.println(b.f(1));
System.out.println(ab.f(1));
}
}

You dont override anything.
The first calling System.out.println(b.f(1)); returns 1, because it works with class B, even the method is named same, but parameters are different (long is not the same as int).
In case when parameters are same (int d), the result would be 1, because it overrides (#Override) the method from the class A.
Now, you know why the second calling System.out.println(ab.f(1)); returns 2. Look from what class it's called from.

Actually the subclass B has inherited the method f(with a long) and has added (overloaded) another method f(with a int).
When you write down a value such as 1 in such a way the compiler, even before assigning it to a typed reference does parse it as an int. More here: Java's L number (long) specification .
When you call the method f using the reference ab (which is A class) it (the reference) says I can only send you to a method f(with a long) and then implicitly cast the type int 1 into a long.
Let's try to change the type of the method in A class to f(short),
then System.out.println(ab.f(1)); will give you this error:
"The method f(short) in the type A is not applicable for the arguments (int)"

Related

How to do Java polymorphism

Edit: should be a2 = new B()
I don't understand why the result for a2.foo(b) is 3 in the following practice question.
I thought with polymorphism, the dynamic types method would run with the method signature that takes the argument that corresponds with the static type.
public class A {
public int foo(Object o) {
System.out.println(1);
return 1;
}
public int foo(A a) {
System.out.println(2);
return 2;
}
}
public class B extends A {
public int foo(A a) {
System.out.println(3);
return 3;
}
public int foo(B b) {
System.out.println(4);
return 4;
}
public static void main(String[] args) {
A a2 = new B();
B b = new B();
a2.foo(b);
}
}
The answer my school has given is a2.foo(b) returns 3, however I thought it would return 4.
Thanks in advance!
There are two things going on here:
Overloading
Overriding
Overloading is about having two different methods in the same class with the same name but different argument types (so they are different). Overriding and polymorphism is about having the same single method in two different classes.
Classes A and B both overload the foo method: they have two methods with the same name. In A one method takes Object as a parameter and one takes A as a parameter. In B one takes A as a parameter and one takes B. Of these four methods, two are the same (foo(A)).
The foo(A) method in B overrides the foo(A) method in A. The foo(B) method however is a different method.
So when you call a2.foo(b) you are calling the foo(A) method. It must be, as a2 is declared as A and A doesn't have a A.foo(B). Since a2 is an actually an object of type B, you are calling B.foo(A) as it overrides A.foo(A).
EDIT: As the question was changed, the answer is now 3 as A.foo(A) is called but overridden.
If a2 was a B then the overridden method would be used, never an overloaded method.
But a2 is an A and which class only has one method foo(A) which can be called, so it prints 2
In short, only the type of this on the left hand side of . will change the choice of method called.
a2 is obviously A, therefore A#foo is executed. It is possible (compiles and executes) since B is instance of A.
Since A#foo is executed, answer is 2 (not 3 and not 4).

type checking and method lookup

I'm confused about the functionality of type checking and method lookup in Java.
From what I understand, type checking is done at the compile time and method lookup is done at the run time.
Type checking is based on the declared type of the reference object whereas method lookup is based on the actual type of the reference.
So suppose the class MyInt is a superclass of the class GaussianInt as follows:
class MyInt
{
private int n;
public myInt(int n)
{
this.n = n;
}
public int getval()
{
return n;
}
public void increment(int n)
{
this.n += n;
}
public myInt add(myInt N)
{
return new myInt(this.n + N.getval());
}
public void show()
{
System.out.println(n);
}
}
class GaussInt extends MyInt
{
private int m; //represents the imaginary part
public GaussInt(int x, int y)
{
super(x);
this.m = y;
}
public void show()
{
System.out.println( "realpart is: " + this.getval() +" imagpart is: " + m);
}
public int realpart()
{
return getval();
}
public int imagpart()
{
return m;
}
public GaussInt add(GaussInt z)
{
return new GaussInt(z.realpart() + realpart(), z.imagpart() + imagpart());
}
And suppose in the main method we have the following:
GaussInt z = new GaussInt(3,4);
MyInt b = z;
MyInt d = b.add(b)
System.out.println("the value of d is:"+ d.show());
Which add method would be used in the show statement inside the print statement in the end?
From what I understand, b is declared to be MyInt, but it is, in fact, GuaussInt. The type checker only sees that b is of MyInt type and that it has add(MyInt) so the code makes sense and compiles.
But then in run time, the method lookup sees that b is of type GaussInt and it has two add() methods, so it will use add(GaussInt) method by looking at method signature and it produces a GaussInt. But d is of type MyInt and method lookup will think it won't work, then will it go back to add(Myint)?
How does the mechanism behind compiling and running of a program work?
From what I understand, b is declared to be MyInt, but it is, in fact,
GaussInt
You are CORRECT. b's reference type is MyInt but it is pointing to an object of GaussInt type.
But then in run time, the method lookup sees that b is of type
GaussInt and it has two add() methods, so it will use add(GaussInt)
method by looking at method signature and it produces a GaussInt. But
d is of type GaussInt and method lookup will think it won't work, then
will it go back to add(Myint)?
As the add method in GaussInt takes a reference of GaussInt type and not of MyInt type. So b.add(b) will call add method of MyInt type. Since the gaussInt has two add methods one take the argument of type MyInt and other takes the argument GaussInt type. So it will call add method of myInt(superclass).
The thing you are trying to achieve is method overriding. For it to work the method signatures should be same. That is, the parent and child class methods should match in every respect, except that the return type of child class method can be subtype of the return type of parent class method
SO in order to achieve what you have mentioned, that is b.add(b) should call add method of gaussInt, make the argument type of add method in both classes same.
Also what you should learn about is dynamic polynorphism(run time check) and static polymorphism(compile time type check).

Inheritance in Java, apparent type vs actual type

Can anyone explain me the result of this execution? I can't notice why each method is called. And how we distinguish the real type vs the apparent type. Thank you :)
public class JavaApplication15 {
public static void main(String[] args) {
A a = new A();
B b= new B();
A ab = new B();
b.f(a);
b.f(b);
b.f(ab);
}
}
public class A {
private final String id="A";
public void f(A x){
System.out.println("Send a fax to "+ x ) ;
}
public String toString(){return id;}
}
public class B extends A{
private final String id="B";
public void f(B x){
System.out.println("Send an email to"+ x ) ;
}
public String toString(){return id;}
}
Result:
Send a fax to A
Send an email to B
Send a fax to B
You are overloading which (per the wikipedia) creates multiple methods of the same name with different implementations. I think you meant to override the f(A x) method with the f(B x) method. Overriding (per the wikipedia) allows a subclass or child class to provide a specific implementation of a method that is already provided by one of its superclasses or parent classes.
Based on the surprise expressed in your question, I think you wanted something like
#Override
public void f(A x) {
System.out.println("Send an email to"+ x ) ;
}
An object of class B has both f(A) and f(B). When you call f(x), it generally chooses the most specific one that matches the type of x. For this, what matters is the type of the reference.
So your a is an A, therefore it calls f(A). Your b is a B, therefore it calls f(B). But what is your ab? The type of the reference is A. So the compiler tells it to call the f(A) overload.
But then, shouldn't it have used the ab object as an A and therefore printed send a fax to A using A.toString() rather than B.toString()?
No, because the choice of method to be called in this case is not determined by the parameter. It's not a choice between overloads as the above choice was, it is a choice between overrides. When deciding which method to use, the one from the superclass or the one from the subclass, the actual type of the object determines it. Since the object referred to by ab is in fact a B, the toString() of B is chosen.
So - among overloaded methods, the one that is chosen is determined based on the number and type of the argument, and the the type of the argument is the type of the reference.
Among overridden methods, the one that is chosen is the one in the actual type of the object instance, regardless of what the type of the reference through which it is invoked.
Note that a method is only considered overridden if it has the same name, number of parameters and respective types of parameters as the parent method.
#Override
public String toString()
{
return id;
}
This defines how the class is outputted. When you call a function such as the following:
b.f(a)
You are inputting a class as the parameter. Because of your toString() method, which is an override of the standard method to output your class, you display the id after Send an email to.
Since B extends A and A has a public method. So it has both of the following methods -
public void f(A x){
System.out.println("Send a fax to "+ x ) ;
}
And -
public void f(B x){
System.out.println("Send an email to"+ x ) ;
}
Actually the seond method in B is an overloaded version of method void f(A x) inherited from A

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...

Can somebody explain why do I get this when I run the program? (simple Java polymorphism)

So, I have these 3 classes in Java.
When I run the program I get:
20,
15,
10,
My question is, why do I get this instead of:
15,
20 (doesn't public int getX(); in class B get us to 15+5=20?),
10
for example?
Can you please explain to me , step by step, what really happens in this program because I am very confused with the output(and the sequence).
public class A {
private int x = 15;
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public void printX() {
System.out.println(this.getX());
}
}
Child:
public class B extends A {
private int x = 5;
#Override
public int getX() {
return super.getX() + x;
}
#Override
public void setX(int x) {
super.setX(x);
super.printX();
}
#Override
public void printX() {
System.out.println(super.getX());
}
}
and
public class C {
public static void main(String[] args) {
A a = new B();
System.out.println(a.getX());
a.setX(10);
a.printX();
}
}
This is happening because you instantiate a as a B object - A a = new B(). It doesn't matter that the explicit type of a is A; it's more generic (abstract) than its real type B (because B inherits from A), therefore polymorphism calls B methods (more specific) in first order. The same applies to fields.
After calling a.getX() class B references to A's getX(), which returns its 15 (superclass method has no reference to the object it was called from in this case), then 5 (B's x) is added, resulting in 20.
The subsequent calls behave in a similar manner.
I have given a basic example similar to your problem go through it you will get your answer. This is the concept of runtime polymorphism
Inheritance creates typecompatibility. It allows a super class reference to refer to the object of sub class. (Reverse is not true).
A super class reference, that refers to object of sub class, can only be used to access the inherited and overrridden methods of sub class. The members newly defined in sub class are not accessible using reference of super class.
class A
{
void f1()//this holds address of object of B
{
System.out.println("A f1");
}
void f2()
{
System.out.println("A f2");
}
}//A
class B extends A
{
void f3()//new method
{
System.out.println("B f3");
}
void f2()//this holds address of object of B
{
System.out.println("B f2 starts");
f3(); //this.f3()
System.out.println("B f2 ends ");
}
}//B
class TypeCmptbl
{
public static void main(String args[])
{
A ref; //reference of A
ref = new B();//Object of B
//ref.inherited() allowed
ref.f1();
//ref.overridden() allowed
ref.f2();
//ref.newMembersOfChild() not allowed
//ref.f3();
}//main
}
Consider the statement
ref.f2();
Here ref is a reference of class A and it has address of object of class B f2() is a overridden method.
When compiler detects such a statement then it doesn't bind the function call with any definition. It only validates the call.
Binding of such calls is left for the runtime environment. At program runtime system identifies the datatype of the object and binds the function call with the function definition provided by the class of object. This type of binding between the function call and function definition is called as "runtime polymorphism" .
Your question is related to the runtime polymorphism in java note that methods are bind at runtime, and the variables are bind at Compile time
In your example
public class C {
public static void main(String[] args) {
A a=new B();
System.out.println(a.getX());
a.setX(10);
a.printX();
}
}
// reference is of A but the object is of B, so at runtime JVM see that memory is of B so the B's method is called, this is runtime Polymorphism
when the below statement is called , the getX() of class B is invoked.
System.out.println(a.getX());
#Override
public int getX() {
return super.getX() + x; // this will add 15 from class A + 5 in this method.
}
the above statement displays 20
when the below statement is called,
a.setX(10);
#Override
public void setX(int x) {
super.setX(x); // observe this method, this prints 15
super.printX(); // this prints 10
}
//super.setX(x); it will call
public void setX(int x) {
this.x=x; // 10 <--- 15 so 15 is displayed
}
here this.x refers the value which is passed through a.setX(10).
A a = new B();
So the concrete type of a is B.
System.out.println(a.getX());
You're calling getX() on an object of type B. So the following method is called, because the concrete type of a is B, and B has overridden the getX() method defined by A:
public int getX() {
return super.getX() + x;
}
It adds B's x (whose value is 5), with the result of super.getX(). This method, in A, is defined as
public int getX() {
return x;
}
So it returns A's x, which is initialized to 15.
The result is thus 5 + 15 = 20.
The rest can be explained the same way. Remember that fields are not accessed in a polymorphic way. Only methods are. So, inside the code of A, when you see x, it always mean "the value of the field x in A". Inside the code of B, when you see x, it always mean "the value of the field x in B".
When you say:
A a = new B();
it means Object of A is instantiated with class B. So, in the memory, a space is reserved for your object 'a' which contains all the methods and properties of class B (not A).
So, when the first print statement is executed, it executes the getX() method of the class B and not the getX() method of class A.
For other methods called by your object 'a', the methods of the class B are called.
This is also known as dynamic binding, as JVM allocates the memory to the object 'a' at the run time and not compile time.
For more details on dynamic binding check these links:
http://www.tutorialspoint.com/java/java_overriding.htm
http://www.tutorialspoint.com/java/java_polymorphism.htm
I also suggest you to instal eclipse on your machine and run your code in the debug mode.
This is the best way you can study your code.

Categories

Resources