I am thinking about this java oop problem . I don't exactly know exactly what is really happening there . Can someone make me understand ?
abstract class A {
public int proc (A p){
return 98;
}
}
class B extends A {
public int proc(A p) {
return 17;
}
}
class C extends A {
public int proc (C p) {
return 65;
}
}
public class HelloWorld{
public static void main(String []args){
C x = new C(); // here x is C type and is an instance of C ?
A y=new B(); // here y is A type and is an instance of B?
C z=new C(); // here z is C type and is an instance of C ?
System.out.println(y.proc(x)+z.proc(x)); /* y is A type so it is looking for proc function in A ,but doesn't return 98
, z is C type and it is looking for proc function in C and return 65 .*/
}
}
Can someone tell me how should I tackle theese instances ?
Y is an A but contains a reference to a B so when we call y.proc it is the proc in B that is called, and returns 17, not 98.
You need to look at the instance that is created and not the type of variable.
In Java, you can create base class objects which hold the child classes objects except for abstract classes.
A is an abstract class, you cannot instantiate it, but you can assign an object of the child class to it which holds the child class object's features.
You can think, we are assigning the reference of B to y which has a type of A.
System.out.println(y.proc(x));
The code above will print 17, which is the return value of the proc in class B returns.
Whenever you call the methods of y, the compiler will give you class B's methods automatically.
So, you are creating an instance of class B in the memory and assigning it to y which points to the same memory location.
For that reason, you can use the methods of class B.
Same goes for z as well.
Related
I'm struggling to understand the C() object created in this code.
I understand that when it is created on line 3, it is an object with the reference in the A class. I also understand that you can reference the same object on line 4 from a reference in the B class. However, I don't understand the casting of reference o1 on line 4. Does this change the object or just how it is referenced?
Would really appreciate an explanation :) thanks
public class TestClass{
public static void main(String args[ ] ){
A o1 = new C( );
B o2 = (B) o1;
System.out.println(o1.m1( ) );
System.out.println(o2.i );
}
}
class A { int i = 10; int m1( ) { return i; } }
class B extends A { int i = 20; int m1() { return i; } }
class C extends B { int i = 30; int m1() { return i; } }
In
A o1 = new C( );
you assign an object of type C to a variable of type A.
o1 can reference any object of class A or any sub-class of A (such as B and C). However, once you assign an object of class C to a variable of type A, you can only use that variable to execute methods declared in class A (or any super class of A).
If you want to execute methods of class B, you must tell the compiler that this variable actually references an object of class B (which is true, since that variable holds a reference to an object of class C, which is also of class B, since C extends B).
That's what the cast is for:
B o2 = (B) o1;
Now, using the variable o2, you can call methods declared in class B.
However, since all 3 classes declare a method of the same signature (int m1( )), the cast doesn't allow you to call a method you couldn't call via the o1 variable. It does, however, give you access to the instance variable i of class B (by writing o2.i).
Does this change the object or just how it is referenced?
It doesn't change the object. It just gives the compiler more detailed information about the actual type of the object referenced by that variable.
class A {
public int a = 100;
}
class B extends A {
public int a = 80;
}
class C extends B {
public int a = 10;
public void show() {
int a = 0;
System.out.println(a);
System.out.println(super.a);
System.out.println(((A) this).a);
}
}
What does ((A) this).a in the line System.out.println(((A) this).a); do?
Is it upcasting/downcasting thisor is something else happening here?
I also tried System.out.println(this); and System.out.println((A)this); and they both have the same output. What exactly is happening here?
In the java programming language, we have classes. When we write java code, we create instances of those classes, for example:
Object o = new Object();
Object is a class. Writing new Object() creates an instance of that class. The above code declares a variable o and assigns it [a reference to] an instance of class Object.
In the terminology of the java programming language, we say that variable o has type Object.
In the code in your question, a variable that is assigned an instance of class C, really has three types.
It has type C.
It has type B since B is the superclass of C.
It has type A because it indirectly extends class A also.
In the context of the code in your question, this is a special variable whose type is C. Writing (A) this is telling java to relate to the variable this as if its type is A.
Class A cannot access its subclasses. Hence it is only aware of its class member a. Hence when you write this line of code...
((A) this).a
You are accessing the member of class A only.
System.out.println(a);a is the one from the show method of your C class → a = 0
System.out.println(super.a);a is the one from the super-class of C, which is B → a = 80
System.out.println(((A) this).a);First, you cast your C instance (this) into A, then you call a which is a member of the A class → a = 100
There is also something to consider : method will always take the more specialized one (except if super is used), where field will be taken directly from the type referenced (even if there is an extending class).
For example, if I add getA() in each classes :
class A {
public int a = 100;
public int getA(){
return a;
}
}
class B extends A {
public int a = 80;
public int getA(){
return a;
}
}
class C extends B {
public int a = 10;
public int getA(){
return a;
}
public void show() {
int a = 0;
System.out.println(a);
System.out.println(super.a);
System.out.println(((A) this).a);
System.out.println(getA());
System.out.println(super.getA());
System.out.println(((A) this).getA());
}
}
class Scratch {
public static void main(String[] args) {
new C().show();
}
}
I get the following output :
0
80
100
10
80
10
Which means that in the case of the method, except in the case of super.getA() which explicitly goes to the superclass, casting your C into a A doesn't change much for methods, as it impacts the field.
If you write something like obj.a, obj.getA() or someMethod(obj), Java somehow has to find the actual field or method to be used, based on the type or class of obj. There are two distinct dispatch mechanisms involved (plus the special construct super).
Dynamic dispatch (polymorphism, overriding): This is used when calling an instance method on the object, as in obj.getA(). Then the runtime class of the obj is examined, and if this class contains a getA() method, this is used. Otherwise, the direct parent class is examined for a getA() method, and so on up to the Object class.
Static dispatch: In cases like obj.a or someMethod(obj), the runtime class of obj doesn't matter. Involved is only the compiler, and from his knowledge of obj's type, he decides which field or method to use.
super dispatch: If you write super.getA() or super.a, your getA() method or a field is ignored, and instead the next-higher class in the hierarchy is used that contains such a method or field.
In your case you have 3 fields plus one local variable, all with the same name a. (By the way, it's a very bad idea to have such name conflicts in professional code.) We are inside a method show() declared in the C class. Let's have a look at some different expressions and what they mean here:
a references the local variable a. There's no dispatch needed, it's just that local definitions take precedence over fields.
this.a is a static-dispatch expression, so it's important what the compiler thinks about the type of this. And that's always the class where this code has been written. In your case, it's class C, so the field a from class C is used, the one being 10.
super.a is a super-dispatch expression, meaning that the a field from this class C is ignored and the next higher one taken (the one from B, in our case).
((A) this).a is static dispatch, but the (A) casting has a significant effect. The expression before the dot originally comes from this, being of type C, but the (A) cast tells the compiler to believe it were of type A. This is okay, as every C also is an A, by inheritance. But now, static dispatch sees something of type A in front of the dot, and dispatches to the a field from the A class, and no longer from C.
getA(), this.getA() and ((A) this).getA() are all dynamic-dispatch examples, all giving the same result. The method called will be the one based on the runtime class of this object. This will typically be one defined in the C class. But if show() was called on an object of a subclass of C, e.g. D, and D had its own getA() method, that one would be used.
super.getA() is a case of super-dispatch, it will call the getA() method next higher up in the class hierarchy from the current class, e.g. B.
System.out.println(this);
And
System.out.println((A)this)
These two prints the object reference to class C with toString() method.
System.out.println(((A)this).a);
This is upcasting, child object to parent object.
At university we were given a Java program and tasked with understanding how the output comes to be the way it is. The program is the following:
interface A {
public void f(A x);
}
interface AA extends A {
public void f(B x);
}
class B implements A {
public void f (A x) {System.out.println("1");}
public void f (B x) {System.out.println("2");}
public void f (C x) {System.out.println("3");}
}
class C implements A,AA {
public void f(A x) {System.out.println("4");}
public void f(B x) {System.out.println("5");}
public void f(C x) {System.out.println("6");}
}
public class Task7 {
public static void main(String[] args) {
B b = new B(); C c = new C();
A ac = c; A ab = b;
AA aac = c;
b.f(b); c.f(c);
ac.f(b); ab.f(b);
aac.f(b); aac.f(c);
}
}
The output is "264154". I don't really understand how the last 4 numbers can be explained. can anybody help?
EDIT: To explain what is my problem a little bit further:
´b.f(b)´ obviously will print out 2 because you are giving a B reference to a B object, and ´c.f(c)´ will print 6 for the same reason.
´ab.f(b)´ will call ´b.f(b)´ because its dynamic type is B. Now, I don't understand why the argument ´b´, which before has been seen by the same class as a ´B´, is now understood as an ´A´, so that "1" gets printed instead of "2". And the same goes for the other method calls, I just don't understand why the same argument with the same underlying object is interpreted differently
Polymorphism applied to the object on the left of the . only. The compiler determines which method signature to call at compile time, regardless of the value passed.
e.g.
B b = new B();
b.f((A) null);
b.f((B) null);
b.f((C) null);
prints 123 as only the type of the reference known at compile time matters.
Similarly, when invoking a static method, only the type of reference matters if you use a reference.
Thread t = null;
t.yield(); // call Thread.yield() so no NullPointerException.
I just don't understand why the same argument with the same underlying object is interpreted differently
The method signature is determined at compile time based on the reference type.
Another way of looking at it is that polymorphism only applied for overridden methods, not overloaded methods.
First of all you have to really understand polymorphism.
I'm not going to explain why the first two values are printed out, but I consider interesting knowing why the other ones have those outputs.
So, let's check the third one: ac.f(b); ac is an instance of A: A ac = c; and c is an instance of C: C c = new C();. Therefore, A ac = new C(); which means that ac can only use functions inside C class and among those functions it can only call the ones written inside A interface: public void f(A x) {System.out.println("4");} (The compiler doesn't care about the type of object in the parameters section)
Other example: ab.f(b); that's the fourth number you're getting in the output. ab is an instance of A: A ab = b and b is an instance of B: B b = new B();. Thus, A ab = new B();. Which implies that ab can call all functions declared inside B and inside A that's why: public void f (A x) {System.out.println("1");}.(Remember they must be declared in both sections, not just in one).
I am facing some problems about inheritance in Java.
I can't understand why the following two programs have those outputs!
Could anyone help me? :)
1)
public class A {
int foo() {
return 1;
}
}
public class B extends A {
int foo() {
return 2;
}
}
public class C extends B {
int bar(A a) {
return a.foo();
}
}
C x = new C();
System.out.println(x.bar(x));
// OUTPUT:2
2)
public class A {
int e=1;
}
public class B extends A {
int e=2;
}
public class C extends B {
int bar(A a){
return a.e;
}
}
C x= new C();
System.out.println(x.bar(x));
// OUTPUT:1
In both cases, you're passing in an object of type C into the print function. The bar function asks for an object of type A, but it's still acceptable for you to pass in an object of type C since it is a subclass of A. So first of all, it's important to keep in mind that a.foo() and a.e are being called on a C object.
So what is happening in both cases is that it's searching for the lowest attribute or method in the list. Here is a very simplified version of what Java is doing in part 1:
Hey, you've passed in an object of type C to the bar method! Now let's call its foo method.
Whoops! C doesn't have a foo method! Let's take the next step up to the B class to see if it has a foo method.
Yay! B has a foo method, so let's call it. No need to work our way up to the A class because we've already found what we need in B.
It's all about understanding that the parameter was downcast from A to C. The exact same sort of logic is used in part 2. It notices that an object of type C was passed in, so it gets the e attribute from object B since its the lowest class in the hierarchy that contains that attribute.
Hopefully that answers your question!
The question might be a very basic one. I am new to Java so please bear with me.
My code:
class A
{
int b=10;
A()
{
this.b=7;
}
int f()
{
return b;
}
}
class B extends A{ int b; }
class Test
{
public static void main(String[] args)
{
A a=new B();
System.out.println(a.f());
}
}
Why is the output 7? Doesn't class B get its own instance variable b?
It would but the function f can only see the version of b that is in A. Thus the function returns 7.
If you were to copy the function f into the class B you would see the member b of the class B being returned.
As Hiding instance variables of a class explains, Java variables are not polymorphic. The 2 b variables are 2 different variables as you would expect, but when you call the function A.f it can only see the one b variable that A has. So it returns A.b and NOT B.b.
So to answer your question, class B DOES get its own instance variable b, and it is completely independant of A.b but you currently have no way to access it so you cannot see its value.
Your type reference is A:
A a = new B();
Thus instance fields/static fields and static methods will be provided from A, as long as concerned method (in your case f()) isn't overriden by B.
In other languages, as Scala, variables can be redefined in subclasses and targeted even from a supertype reference.