abstract class A {
int met(A a) {
return 0;
}
int met(B b) {
return 1;
}
int met(C c) {
return 2;
}
}
class B extends A {
int met(A a) {
return 3;
}
int met(B b) {
return 4;
}
int met(C c) {
return 5;
}
}
class C extends B {
int f() {
return ((A)this).met((A)this);
}
}
public class teste {
public static void main(String args[]) {
C x = new C();
System.out.println(x.f());
}
}
The program will return 3 and I was expecting 0. Why does the first cast in the method f do nothing and the second one works? Is it because in the A and B classes the met methods are overloaded and therefore static binding is used?
That's just the way polymorphism works. Just consider this example:
A a = new C();
a.met(a);
This would as expected call the correct method B#met(...). The method-tables for an object don't just change because you change the type of the variable you stored the Object in, since the binding between an Object and it's methods is stronger than the one between the storage-type and the methods related to it. The second type works, because the type of the input is casted to A and thus the method recognizes it as A (the type of the input-storage has stronger binding than the Object type).
Related
This question already has answers here:
Is there a way to override class variables in Java?
(17 answers)
Overriding member variables in Java ( Variable Hiding)
(13 answers)
Closed 5 years ago.
I am not able to understand the following output.
I don't know why the output is 10, I think the line A a = new B() creates a new instance of class B, I think the result should be 20
class A {
int i = 10;
}
class B extends A {
int i = 20;
}
public class MainClass {
public static void main(String[] args) {
A a = new B();
System.out.println(a.i);
}
}
Why this works like this .. please explain.
First, see Hiding Fields (emphasis added)
Within a class, a field that has the same name as a field in the superclass hides the superclass's field, even if their types are different
In other words, this isn't "inheritance" since you're actually hiding A's i behind B's i, and you are using a reference object of A, so you are getting its fields. If you did B b = new B(), you would see 20, as expected.
If you expect true overrides, try using methods.
class A {
public int get() {
return 10;
}
}
class B extends A {
#Override
public int get() {
return 20;
}
}
See
A a = new B();
System.out.print(a.get()); // 20
If you really want to see both at once, see this example.
class A {
int i = 10;
}
class B extends A {
int i = 20;
#Override
public String toString() {
return String.format("super: %d; this: %d", super.i, this.i);
}
}
And
A a = new B();
System.out.print(a); // super: 10; this: 20
In java you cannot override an instance variable. The output you are getting is expected. In Java you can only override instance methods and not instance variables.
If you want 20 as an output you may use getter methods over those instance variables.
class A {
int i = 10;
int getI() {
return i;
}
}
class B extends A {
int i = 20;
int getI() {
return i;
}
}
public class MainClass {
public static void main(String[] args) {
A a = new B();
System.out.println(a.getI());
}
}
Polymorphism is not applicable for fields in Java.Evaluating Variables decision is taken at compile time so always base class variables are accessed.
Because you define 2 variables: one in the subclass B, and one with the same name in superclass A.
A a = new B();
a.i; // refers to A.i
If you cast the A to a B, it will access B.i:
System.out.println(((B)a).i);
I think you need to use 1 variable:
class A {
int i;
public A() {
i = 10;
}
}
class B extends A {
public B() {
i = 20;
}
}
public class MainClass {
public static void main(String[] args) {
A a = new B();
System.out.println(a.i); // will print 20
}
Member variable i is already defined in class A.
In order to achieve what you are looking for, change the class B as shown below:
class B extends A {
public B() {
i = 20;
}
}
I have the following java code:
class A {
int someMethod () { return 1; }
int someMethod (A a) { return 2; }
int someMethod (B b) { return 3; }
int someMethod (C c) { return 4; }
static A anotherMethod ( Object obj) { return (A) obj; }
}
class B extends A {
int someMethod () { return 6; }
int someMethod (A a) { return 7; }
int someMethod (B b) { return 8; }
int someMethod (C c) { return 9; }
static A anotherMethod ( Object obj) { return (B) obj; }
}
class C extends A {
int someMethod () { return 11; }
int someMethod (A a) { return 12; }
int someMethod (B b) { return 13; }
int someMethod (C c) { return 14; }
static C anotherMethod ( Object obj) { return (C) obj; }
}
public static void main ( String [] args ){
A a = new A(); B b = new B(); C c = new C();
System .out. println (A. anotherMethod (b). someMethod (b));
}
As expected the output is 8.
Ok now i delete the someMethod(B b) in class A:
class A {
int someMethod () { return 1; }
int someMethod (A a) { return 2; }
int someMethod (C c) { return 4; }
static A anotherMethod ( Object obj) { return (A) obj; }
}
I discussed the output with my friends, but nobody could explain exactly why we get a 7 as output now?!?!???
This happens because this snippet:
A.anotherMethod(b)
gives you an object typed to A. You then call:
.someMethod(b)
on that instance. Now, seeing as the A class doesn't have a someMethod(B b) method any more, it will instead call someMethod(A a) - which it can do because B is a subclass of A.
Because the instance you called the method on is actually of type B, and the B class overrides someMethod(A a) that's the one that ends up being called, hence your output of 7.
This is because you are casting B object to A firstly and then you have a reference of type A inside a variable called b and when you pass b to the method what you are really passing is a reference to A.
A.anotherMethod (b) // Casts and returns a reference of type A.
.someMethod(b) // What you really have here is a reference of type A
so this will call the someMethod(A a) and therefore will output 7.
You can not override static methods in java.
Even if you override that will not consider or work as overriden method.
Below link is for your reference.
Can I override and overload static methods in Java?
If code same scenario in more simple way, then everything becomes clear:
public class Playground {
public static void main(String[] args) throws Exception {
B b = new B();
A casted = (A) b;
System.out.println(casted.someMethod(b));
}
}
class A {
int someMethod(A a) { return 2; }
int someMethod(B b) { return 3; }
}
class B extends A {
int someMethod(A a) { return 7; }
int someMethod(B b) { return 8; }
}
Hence, we got 'casted' object which is instance of B, but casted to A. When we call someMethod(b) on it, JVM pick up A.someMethod(B b) and exeutes its overrided version. In case when A.someMethod(B b) is not presented, JVM pick up A.someMethod(A a) and executes its overrided version.
Trying to pass a java test I faced the following question
class A {
int f() { return 1; }
}
class B extends A {
int f() { return 2; }
}
class C extends B {
int f() { return 3; }
int test() {
return super.f() +
((A)this).f();
}
}
Can't figure out why ((A)this).f() returns 3 but not 1?
This is dynamic dispatch, the static type of the object ((A)this, which is A) does not matter, only the dynamic type, and that is C.
Similarly, if you do
A a = this;
a.f();
The same value (3) will be returned.
Why does below code prints "1" ?
class A {
int x = 1;
}
class B extends A {
int x = 2;
}
class Base {
A getObject() {
System.out.println("Base");
return new B();
}
}
public class CovariantReturn extends Base {
B getObject() {
System.out.println("CovariantReturn");
return new B();
}
/**
* #param args
*/
public static void main(String[] args) {
Base test = new CovariantReturn();
System.out.println(test.getObject() instanceof B);
System.out.println(test.getObject().x);
}
}
Because you are referring to fields, which are not affected by polymorphism. If you instead used getX(), it would've returned 2.
What you are asking is, the value of field x defined in class A (because Base.getObject() returns A). Even though CovariantReturn overrides the method to return B, you are not referring to your object as CovariantReturn.
To expand a bit on how fields are not affected by polymorphism - field access is realized at compile time, so whatever the compiler sees, that's what's accessed. In your case the method defines to return A and so A.x is accessed. On the other hands methods are invoked based on the runtime type. So even if you define to return A but return an instance of B, the method you invoke will be invoked on B.
#kris979 Though you are returning B, i think what makes the difference is that the return type is of A. Hence value of x in A i.e. 1 is printed.
As Bozho pointed out - instance variable are never affected by polymorphism. Let me give you a quick small example.
class Base {
int i = 1;
void method() {
System.out.println("in base");
}
}
class Sub extends Base {
int i = 2;
void method() {
System.out.println("in sub");
}
}
public class Test {
public static void main(String[] args) {
Base obj = new Sub();
obj.method();
System.out.println(obj.i);
}
}
This code will print - in sub and 1
I have 2 classes:
public class A
{
int n = 10;
public int getN()
{
return n;
}
}
public class B extends A
{
int n = 20;
public int getN()
{
return n;
}
}
public class Test
{
public static void main(String[] args)
{
B b = new B();
System.out.println(b.getN()); //--> return 20
System.out.println(((A)b).getN()); //--> still return 20.
//How can I make it return 10?
}
}
All methods in Java are always virtual. That is, there is no way of invoking the "super"-version of the method from the outside. Casting to A won't help as it doesn't change the runtime type of the object.
This is probably your best alternative / workaround:
class A {
int n = 10;
public int getN() {
return n;
}
public final int getSuperN() { // "final" to make sure it's not overridden
return n;
}
}
class B extends A {
int n = 20;
public int getN() {
return n;
}
}
public class Main {
public static void main(String[] args) {
B b = new B();
System.out.println(b.getN()); // --> return 20
System.out.println(((A)b).getN()); // --> still return 20.
System.out.println(b.getSuperN()); // --> prints 10
}
}
you can't make the value be "10" because the instance of the object was for class B, and when you do the cast the only thing that are you doing is changing the define class not setting values for the object B, in other words if you need to get 10 its' something like this
b = new A();
That thing won't work due to polymorphism. Class B is still class B even if you cast it into its super class.
I think you'll need something like this:
public class B extends A
{
int n = 20;
/**
* #return the super n
*/
public int getSuperN()
{
return super.n;
}
}
What you see is polymorphism in action. Since b is a B, that method (which returns 20) is always called (regardless if you cast it to an A).