Instant of interface and class - java

In my code I have seen difference between instant of interface and instant of class that implement it , why ??
I have method that return array of objects of class and implements an interface which declare this method , when create instant of class and invoke this method the returned value is different if it was invoked by interface instant although it should do the same job , the returned value is different , why??
public interface A{
public B[] m();
}
public class B implements A {
public B[] m() {
B b[]=new B[10];
for(int i=0; i>10; i++)
b[i]=new B();
return b;
}
}
In this part when I try to create two instant one for class and another for interface then invoke the method for each one like :
B obj1=new B();
A obj2=new B();
System.out.println(obj1.m().equals(obj2.m));
System.out.println( obj1.m()[0].equals(obj2.m()[0]) );
........
This returned false.
Maybe it is clear obj1 is not obj2, but why is the returned value different and how can I get same returned value if possible?

The behavior of your code have nothing to do with the compile time type of obj1 (B) vs. obj2 (A).
The reasons your comparisons return false :
Comparing the arrays would always return false for two distinct arrays, since arrays don't override Object's equals method.
Comparing the first element of the two arrays also returns false, since your B class doesn't override the equals method, so obj1.m()[0].equals(obj2.m()[0]) is false since obj1.m()[0] != obj2.m()[0]. It can only return true if your B class would have an implementation of public boolean equals (Object other) that may return true.

You are comparing objects, that will never be same, unless you override the equals method.
You should compare the contents.
There is no difference between declaring objects, in your case
Case1: B obj1=new B();
Case2: A onj2=new B();
In case1 you are directly assigning to Object B so you are eligible to call method specific to B along with implemented methods from A.
In Case2 you are only eligible to call the methods implemented from Interface A
It is called polymorphism.
Correcting your code will give the right answer, as answered by Eran

Related

Why does it seem to call the wrong method?

Lets say I have two classes A and B . B inherits from A and B has the following methods:
public boolean equals(Object other) {
System.out.print("Object");
return true;
}
public boolean equals(A other){
System.out.print("A object");
return true;
}
public boolean equals(B other) {
System.out.print("B object");
return true;
}
A a1 = new A();
A ab = new B();
B b1 = new B();
what is unclear to me is why
ab.equals(a1)
ab.equals(b1)
Returns Object
ab is an instance of B with pointer of A. a1 is clearly both instance and pointer of A. So Why does it use the Object other instead of A other method?? same goes for b1 which is an instance of B with pointe B yet the compiler chose to apply the equals method like I inserted regular object?? AM i that stupid or is this language incoherent?
BTW A doesn't have any equals methods at all.
Explanation
BTW A doesn't have any equals methods at all.
But you do
ab.equals(a1)
ab.equals(b1)
And ab is:
A ab = new B();
So while it is actually a B, the variable is of type A.
Javas rules for choosing methods in such situations will start looking for an equals method in the A class. And it actually has one, the default implementation inherited from Object. It has the signature
public boolean equals(Object other)
So it decides for this signature. Now it asks the actual instance behind ab, which is of type B, for a method with that signature. It chooses the overriden implementation in B:
public boolean equals(Object other) {
System.out.print("Object");
}
And consequentially prints Object in both cases.
Details
The details for this are defined in JLS§15.12. Method Invocation Expressions. It talks about finding the most specific match. The rules can get quite complex if you dive deep into it.
Some excerpts:
The first step in processing a method invocation at compile time is to figure out the name of the method to be invoked and which class or interface to search for definitions of methods of that name.
The second step searches the type determined in the previous step for member methods. This step uses the name of the method and the argument expressions to locate methods that are both accessible and applicable, that is, declarations that can be correctly invoked on the given arguments.
There may be more than one such method, in which case the most specific one is chosen. The descriptor (signature plus return type) of the most specific method is the one used at run time to perform the method dispatch.
The class or interface determined by compile-time step 1 (§15.12.1) is searched for all member methods that are potentially applicable to this method invocation; members inherited from superclasses and superinterfaces are included in this search.
If more than one member method is both accessible and applicable to a method invocation, it is necessary to choose one to provide the descriptor for the run-time method dispatch. The Java programming language uses the rule that the most specific method is chosen.
The setup
Given a class A and a class B extends A, overriding and overloading equals(...) with different parameter types as follows:
class A {}
class B extends A {
public boolean equals(Object other) {
System.out.println("Object");
return true;
}
public boolean equals(A other) {
System.out.println("A object");
return true;
}
public boolean equals(B other) {
System.out.println("B object");
return true;
}
}
The question
Given the following code
A a1 = new A();
A ab = new B();
B b1 = new B();
ab.equals(a1);
ab.equals(b1);
Why is "Object" printed out for both calls?
The explanation
The signature of method called is determined through the static type of the receiver and the static type of the parameters (as described in JLS, §15.12.3). Furthermore, through dynamic dispatch, a child-class override of a method may be executed.
If we analyze the type of ab (the receiver of the call), we find it to be A. There is only one method called equals(...) wihtin A, which is equals(Object) (inherites from Object). the parameters (a1 and b1 respectively) are assignable to Object, so this method is called.
Through dynamic dispatch, equals(Object) in B is actually executed and "Object" is printed out for both calls.
A full example is available on Ideone

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

Why is the equal not using the casted equals method?

Simply the just as the question have stated. The answer should ideally be false, since it would be using the Object#equal which is simply reference comparison.
String cat = new String("cat");
String cat2 = new String("cat");
System.out.println(((Object) cat).equals((Object) cat2)); // returns true, but should be false
This has to do with polymorphism; I know how equals() and interning work.
RELATED TOPICS: CASTING GRAPHICS -> GRAPHICS2D
The aforementioned scenario is a case of upcasting where String is being downcasted to Object.
However, a common use of this is actually downcasting Graphics to Graphics2D to use upgraded or new method that don't exist in Graphics itself. How come we can upcast and NOT downcast.
import java.awt.*;
import javax.swing.*;
public class Example extends JPanel {
public static void main (String []args){
JFrame frame = new JFrame();
}
public void paintComponent(Graphics g){
Graphics2D g2 = (Graphics2D) g; // How can we be sure the informal
g2.drawLine(0,0, getWidth(), getHeight()); // parameter contains those methods?
}
}
You cast cat to Object, but that doesn't change the fact that cat is a String instance. Java performs dynamic binding (aka late binding), meaning that method invocations are resolved at runtime based on the class of which the object is an instance. In this case, that's still String, which means String#equals() will be used, not Object#equals(). The fact that you cast cat2 to Object makes little difference -- equals() takes an Object argument anyway.
Here's an easy way to prove this to yourself:
String s = "abc";
Object o = (Object) s; // we don't really need an explicit cast
System.out.println(s.getClass());
System.out.println(o.getClass());
class java.lang.String
class java.lang.String
The same principle is at work here. o is of type Object but it is a String instance, and so String's getClass() is called.
Consider the following class structure:
class A {
public void foo() {
System.out.println("A foo");
}
}
class B extends A {
public void foo() {
System.out.println("B foo");
}
public void bar() {
System.out.println("B bar");
}
}
Now, when we have something like
A b = new B();
b.foo();
then B's foo method will be invoked. This is the phenomena described above. You're asking about something like:
A b = new B();
b.bar(); // error
The reason we have an error here is because there is no guarantee that b will have a bar() method. For all we know (or, rather, the compiler knows), b could be a C instance with who-knows-what. For this reason, we have to perform an explicit cast:
A b = new B();
((B) b).bar();
This follows from the fact that Java is statically typed (even though it performs dynamic binding).
Instance methods are resolved at run time based on their dynamic type. This is polymorphism/late binding. Regardless of you casting the object to a static type of Object, it's runtime type is still String, so String#equals(Object) will be used.
How come we can upcast and NOT downcast.
Given two classes
public class A {
}
public class B extends A {
public void doSomething() {}
}
and
A a = new B();
a.doSomething(); // this won't compile because A doesn't declare a doSomething() method
((B) a).doSomething(); // this is fine because you are now calling the method on the static type B
// you might get a ClassCastException here if the runtime type of a wasn't B
As all the methods are default virtual in java so even though you type casted it to Object it will call String equals method because the object is of type String not of Object.
This is also called late binding or runtime polymorphism.
That's not how Java resolves which method should be used. Even though you are casting it to Object at runtime String's equals will be used. And String's equals doesn't check reference equality but if the strings are "logically" equal.
This is due to so called "dynamic linking" you can google it or try reading about it here.
String Object is one of the immutable objects, others like Integer.
So here is a simple comparison, you created 2 Integer objects(the same value) and do equal operation. It makes more sense returning the 2 Integers are equal.
And from the example, I guess you might now know the objective of immutable classes: they are designed to retain their state and simplify operations relate to them, just like an int.

Java calling subclass method when trying to use parent class method

If I have two classes, A and B,
public class A {
public int test() {
return 1;
}
}
public class B extends A{
public int test() {
return 2;
}
}
If I do: A a1 = new B(), then a1.test() returns 2 instead of 1 as desired.
Is this just a quirk of Java, or is there some reason for this behavior?
This is called polymorphism. At runtime the correct method will be called according to the "real" type of a1, which is B in this case.
As wikipedia puts it nicely:
The primary usage of polymorphism in industry (object-oriented
programming theory) is the ability of objects belonging to different
types to respond to method, field, or property calls of the same name,
each one according to an appropriate type-specific behavior. The
programmer (and the program) does not have to know the exact type of
the object in advance, and so the exact behavior is determined at
run-time (this is called late binding or dynamic binding).
No, that is correct (it is due to polymorphism). All method calls operate on object, not reference type.
Here your object is of type B, so test method of class B will be called.
This is polymorphism and more specifically in Java overriding. If you want to invoke Class A's test method from Class B then you need to use super to invoke the super classes method. e.g:
public class B extends A{
public int test() {
return super.test();
}
This is intended behavior. The method test() in class B is overriding the method test() of class A.
For
A a1 = new B();
a1 is pointing towards the object of B which is the real type at run-time. Hence value is printed from Object B.
A obj = new A();
obj.test()
will return 1
A obj = new B();
obj.test()
will return 2
B obj = new B();
obj.test()
will return 2
As stated in other answers this is how polymorphism works.
This post may make things a bit clearer
Java uses dynamic binding (or late binding), so the method of B is called, not A. This is the opposite of static binding. There is a nice example here.
You declare your object as A but your instance is B. So the method which will be called is from class B. B extends A(we can say that A is parent for B) if you will comment method test in B and then recall this method, in this case the method invoked will be test from A class and will return 1.

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