I do not understand 'this' being used with a superclass - java

I have two classes and an interface shown below.
Quick summary: Interface Winterface, Class Big, Class Little that extends Big and implements Winterface.
public interface Winterface {}
public class Big {
public int hello = 88;
public Big() {}
public void theMethod() {
System.out.println ("Big was here: " + (this instanceof Winterface) + ", " + this.hello);
}
}
public class Little extends Big implements Winterface{
private boolean hello = true;
public Little(){}
public void theMethod() {
super.theMethod();
System.out.println("Little was here: " + hello);
}
public static void main(String [] args) {
Little l = new Little();
l.theMethod();
}
}
When I execute the main in Little, I get the following output
Big was here: true, 88
Little was here: true
my question is, how can
1) (this instanceof Winterface) return true but
2) this.hello be 88?
If this.hello = 88, then this = Big, which isn't an instance of Winterface.
I do not understand how this is possible, thanks in advance
EDIT: THANKS everyone I understand now that 'this' refers to little, which is a Big and implements Winterface. Since the method is being called as super.theMethod(), the variable 'hello' available is the one in Big even though 'this' refers to little.

this can only be one class. However this.hello is the field accessible to that class.
As this can only be one class it is a Little which has a parent Big and implements Winterface When you call a method in its parent which can only see hello that is what it sees.
i.e. Java supports polymorphism for methods but not fields.

l is Little but Little is a Big and also implements the behavior of Winterface.
The super is a call to the parent class so the hello member of the parent class (i.e. Big) is used.
You are not doing this.hello but super.theMethod() that uses the parent's class member variable hello.
UPDATE:
The super.theMethod() invokes the corresponding method in the parent class. In the parent class you access the fields of the parent (which also belong to the derived class since Little is also a Big). So the this.hello at that point is accessing the part of the code that is of the parent class.
You can imagine the memory print of Little as follows:
++++++++
+ Big +
--------
+Little+
++++++++
So Little has all the members variables of the parent i.e. Big and when the code runs inside super.theMethod() it is running inside the "code area" of Big.
As Peter states in his answer, polymorhism is not supported for methods and I hope that this overly simplistic description helps understand this

This is because the this instanceof ... check does not use the static (i.e., compile-time) type (which is Big), but the object's (this') dynamic run-time type (i.e., this.getClass()), which is Little in your example. If it would use the static type, the operator would be pretty pointless, since we would have:
Object obj = "foo";
if (obj instanceof Object) { /* always entered */ }
/* but */ if (obj instanceof String) { /* never entered */ }
statically, at compile-time. The purpose of the instanceof operator is to enable run-time type testing, for example:
Object obj = /* whatever */;
if (obj instanceof String) {
String str = (String)obj; // Cast cannot fail
...
} else if (obj instanceof Long) {
Long val = (Long)obj; // Cast cannot fail
...
}
Note, that this technique should only be used sparingly.

Your variable is an instance of Big and of Little. It's a direct instance of Little, but since Little inherits from Big the instanceof operator will return true for Big too.
Little l = new Little();
System.out.println(l instanceof Little); // true, l is an instance Little
System.out.println(l instanceof Big); // true, l is an instance of Little which inherits from Big
Your other misunderstanding (I'm assuming) is how the 'method lookup' works. When you call theMethod the it picks Little's implementation of that method. When you call super.theMethod though, you've explicitly said "call Big's version of this method", and then inside that method it's using Big's hello variable rather than Little's hello variable.

What is happening here is that when you are defining your variable hello in Little you are not overwriting the variable hello that is inside Big you are defining a new variable hello within Little that is hiding the variable hello within Big. Thus within the scope of Big, hello will refer to the integer value of 88 and within the scope of Little, hello will refer to true. These are different variables both contained within your object, the only difference is the scope by which you refer to them.
Like others here have said, instanceof is an operator that compares the runtime type of your object (what is returned by this.getClass()). When in Big even though the scope of the variables within your object will refer to Big, this is still of runtime type Little which is why it is an instance of Winterface.

Related

How to distinguish between objects of the same class with different references?

Sorry if the title is poorly worded, I don't really know how to ask this. But I want to distinguish between instances of the same class, but referenced as different classes. Please consider following code:
class Shape {}
class Circle extends Shape {}
class Main {
public static void main(String[] args) {
Circle myCircle = new Circle();
Shape myOtherCircle = new Circle();
System.out.print(myCircle.getClass() + ", ");
System.out.println(myOtherCircle.getClass());
System.out.print((myCircle instanceof Circle) + ", ");
System.out.println(myOtherCircle instanceof Circle);
System.out.print((myCircle instanceof Shape) + ", ");
System.out.println(myOtherCircle instanceof Shape);
System.out.print(Circle.class.isInstance(myCircle) + ", ");
System.out.println(Circle.class.isInstance(myOtherCircle));
System.out.print(Shape.class.isInstance(myCircle) + ", ");
System.out.println(Shape.class.isInstance(myOtherCircle));
}
}
We can distinguish objects by the type of their instance by using the methods or operators shown above, but as shown, when trying to compare objects by the type of the reference there are no differences the code prints this:
class Circle, class Circle
true, true
true, true
true, true
true, true
How can I distinguish myCircle and myOtherCircle by the type reference. Thank you for reading, I appreciate all answers.
I don't think that is possible. The closest you can get is if these variables are fields of a class. Then you can access the type via the class definition:
class Main {
Circle myMainCircle = new Circle();
Shape myMainOtherCircle = new Circle();
static class Shape {
}
static class Circle extends Shape {
}
public static void main(String[] args) throws Exception {
System.out.println(Main.class.getDeclaredField("myMainCircle").getGenericType());
System.out.println(Main.class.getDeclaredField("myMainOtherCircle").getGenericType());
}
}
output:
class Main$Circle
class Main$Shape
The problem I see is "When would you not know the reference type?" For example we could make two methods.
public int special(Circle a){
return 1;
}
public int special(Shape a){
return 2;
}
Then using your example.
System.out.println(special(myCircle) + ", " + special(myOtherCircle));
(This will print 1,2 because java will use the most specified method. myCircle is a Circle and a Shape, but the Circle is the most specified.)
For this to work though, we already know that one class is referenced as a Shape and the other a Circle.
In other words, you want to know, at runtime, the declared type of a reference to a variable (and not a class field - since you can use introspection to check out those, as shown by Conffusion's answer)
Why would you need to check it at runtime? In what case could it be useful to wait until then? The compiler knows much earlier -- at compile time, as it keeps track of the declared types of all identifiers. In your code, if you write
Shape myOtherCircle = new Circle();
// ...
Circle c = myOtherCircle; // compile-time error: invalid implicit cast
This warns you, at compile-time, that you are doing something fishy - as the compiler does not allow implicit (= non-explicit, that is, without an expliccit (Circle) cast) narrowing casts. For example: implicit casting from a Shape to a Circle: bad, because you could try to convert a Square-Shape to a Circle which would lead to run-time errors. From a Circle to a Shape, a broadening cast, no errors can occur.
So, my short answer would be:
you cannot do this at run-time because the compiler (and your IDE) already has this information at compile-time
On the other hand, with computers, almost everything is possible, although some are quite complicated. It is possible to detect such problems at runtime by using the JDK's built-in java compiler to (uh) compile and report on the declared types of variables in any piece of java code - but doing so is certainly not expected (most folks using it just want to compile and run code at runtime, rather than play with the AST), and requires a deep dive into internals. Asides from the JDK's own compiler, you can also use any of a large set of java compilers to do something similar (but beware possible incompatibilities with the standard one).
In Java, a Circle instance is a Circle, no matter if you store a reference to it in a variable declared as e.g. Circle, Shape or Object.
So, anything you do with the instance found in a variable only depends on the instance's class, not on the variable's declared type. That applies to things like the instanceof operator, the getClass() method and so on.
There's one exception: if you have some overloaded methods like
String myType(Object x) { return "Object"; }
String myType(Shape x) { return "Shape"; }
String myType(Circle x) { return "Circle"; }
then the compiler will decide which version to call, based on the type as it is known at compile-time. And if you pass a variable into a call of myType(), the type that the compiler assumes will be the variable's type, not knowing about the class of the instance that will later be referenced in the variable.
So then the following snippet might do what you want:
System.out.print(myType(myCircle) + ", ");
System.out.println(myType(myOtherCircle));
But, as for any given variable you statically know how you declared it, I don't see how such a construct might be useful.

Is it possible to access hidden instance fields in PHP as in Java?

In Java as in PHP, instance fields declared in parent classes are inherited in child classes. Therefore, it is possible to access them using the keyword this (resp. $this in PHP).
In Java, if the child class happens to declare a field with the same name as the parent class, the parent class's field is hidden (see JLS 8.3.1.1-3: Hiding of Instance Variables). It is there, but if the child class wants to access it, it needs to use the keyword super, as in the following example:
class Foo {
protected int x = 1;
}
class Bar extends Foo {
protected int x = 2;
void somemethod() {
System.out.println(this.x); // prints 2
System.out.println(super.x); // prints 1
}
}
Please note that I consider hiding fields as a bad practice, as it only makes for confusing code and easily leads to logic bugs. It is best not to declare instance fields with the same name as an instance field of a parent class. Therefore, this question is of a purely academic nature.
Nevertheless I am curious: Is it in principle possible to access hidden instance fields in PHP, as is possible in Java? Would it be possible to translate the above code snippet to PHP?
<?php
class Foo {
protected $x = 1;
}
class Bar extends Foo {
protected $x = 2;
function somemethod() {
echo $this->x, PHP_EOL; // prints 2
//echo $parent->x, PHP_EOL; // doesn't compile... is there a way to do it?
}
}
Please note that I am talking about instance variables here. Class (i.e., static) variables are a different story altogether and are not a subject of this question.
If it is not possible: Does this mean that the parent instance field effectively gets overwritten in PHP (instead of just hidden), and is thus inaccessible?
The reason why this is not working for you, is because you are overriding the parent. Foo->$x is available in the child scope, therefor when you define X as 2 in Bar it overrides the previous set variable.
If you want something like this to work like in Java, then you would have to use constants.
class Foo {
const x = 1;
}
class Bar extends Foo {
const x = 2;
function somemethod() {
echo parent::x; // prints 1
echo self::x; // prints 2
}
}
Or you could simply change the variable name in Bar and then you would have direct access to it through inheritance.

Java dynamic, static casting

import javax.swing.*;
public class Toast {
static Object[] objects = { new JButton(),
new String("Example"), new Object() };
public static void main(String[] args) {
System.out.println( new Count(objects) );
for (Object o : objects)
System.out.println(o);
}
}
class Count {
int b, s, o;
public Count(Object[] objects) {
for (int i=0; i<objects.length; i++)
count(objects[i]);
}
public void count(JButton x) { b++; }
public void count(String x) { s++; }
public void count(Object x) { o++; }
public String toString() {
return b + " : " + s + " : " + o + "\n";
}
}
Above is a piece of code that appears in some form or the other in past exam papers for one of my upcoming tests. The idea of the question is to gauge if you fully understand polymorphism, dynamic and static casting. Basic ideas of OO.
I would like to put out what I think is correct and if people would be able to correct me or add points that would be greatly appreciated.
From what I can see in the above code:
Items are upcast to objects in the object array as every class in java technically inherits from the object class. This is why when count is run it will say there are 3 objects not 1 Jbutton, 1 string and 1 object.
When the enhanced for loop is run the toString of that object type e.g. Example from the string and memory address of the object (not sure what the JButton will print). As this is done at runtime this is known as dynamic casting.
I cannot see any other points that would be relevant to the above bit of code.
The idea behind static cast and dynamic cast is related to the moment a type decision needs to be made. If it needs to be made by the compiler then it's static cast. If the compiler postpones the decision to runtime then it's dynamic cast.
So, your first observation is incorrect. The upcast does not explain the count. Objects do not loose they type but the compiler needs to perform a static cast to decide which method to invoke and it chooses count(Object). There is no dynamic dispatch in java which means that the method called is always decided at compile time.
You second observation is also incorrect. What is in use is polymorphism. In Java, methods are always invoked for the type of the instance and not for the type in the code. Also, there is no dynamic casting here. The compiler can verify all the types. It's just that method invocation is always virtual but that's not a cast.
Actually in this example, I don't see a single case of dynamic casting. The compiler can verify all types. You normally only see dynamic casting when down casting and there is no case of that.
Here's what I would take away:
The compiler implicitly upcasts when performing assignments. This includes assigning to array elements during initialization.
The compiler and JVM do not implicitly downcast when selecting method overloads. The static type of the objects array is Object[], so the count(Object) method will always be called.
The JVM does implicitly "downcast" (in a sense) when invoking a virtual method. The println loop will always invoke the toString method of the actual object instance rather than always invoking Object.toString.
In your Count() method, always count(object) will be called as all objects are up casted to object.
To prevent that you can call method instance of and then downcast the object and call the count
public Count(Object[] objects) {
for (int i=0; i<objects.length; i++)
{
if(objects[i] instanceof JButton)
count((JButton) objects[i]);
else if(objects[i] instanceof String)
count((String) objects[i]);
else
count(objects[i]);
}
}

Java overloading and inheritance rules

I've been studying because I have an exam and I don't have many problems with most of Java but I stumbled upon a rule I can't explain. Here's a code fragment:
public class A {
public int method(Object o) {
return 1;
}
public int method(A a) {
return 2;
}
}
public class AX extends A {
public int method(A a) {
return 3;
}
public int method(AX ax) {
return 4;
}
}
public static void main(String[] args) {
Object o = new A();
A a1 = new A();
A a2 = new AX();
AX ax = new AX();
System.out.println(a1.method(o));
System.out.println(a2.method(a1));
System.out.println(a2.method(o));
System.out.println(a2.method(ax));
}
This returns:
1
3
1
3
While I would expect it to return:
1
3
1
4
Why is it that the type of a2 determines which method is called in AX?
I've been reading on overloading rules and inheritance but this seems obscure enough that I haven't been able to find the exact rule. Any help would be greatly appreciated.
The behavior of these method calls is dictated and described by the Java Language Specification (reference section 8.4.9).
When a method is invoked (§15.12), the number of actual arguments (and
any explicit type arguments) and the compile-time types of the
arguments are used, at compile time, to determine the signature of the
method that will be invoked (§15.12.2). If the method that is to be
invoked is an instance method, the actual method to be invoked will be
determined at run time, using dynamic method lookup (§15.12.4).
In your example, the Java compiler determines the closest match on the compile type of the instance you are invoking your method on. In this case:
A.method(AX)
The closest method is from type A, with signature A.method(A). At runtime, dynamic dispatch is performed on the actual type of A (which is an instance of AX), and hence this is the method that is actually called:
AX.method(A)
I will clarified it in more simple way. See when you making sub class object with super class reference like here you did.
Always one thing keep in your mind that when you call with super class reference, no matters object is of sub class it will go to the super class, check method with this name along with proper signature is there or not.
now if it will find it, than it will check whether it is overridden?? if yes than it will go to the sub class method like here it went. another wise it will execute the same super class method.
I can give you the example of it...just hide
public int method(A a) {
return 3;
}
method & check your answer you will get 1 2 1 2, why because it gives first priority to reference. because you overridden it & than calling it, so its giving 3..!! hope its big but easy to understand. Happy Learning
a2 referenced as an A and the JVM using the reference first (not the acutal object as you expected).

Upcasting in Java and two separate object properties

Trying to understand upcasting in Java. Recently observed strange behavior.
Example:
public class A extends B {
public int i = 2;
public void printI() {
System.out.println("print i = " + this.i);
}
public static void main(String[] args) {
B a = new A(); // <- upcasting here
System.out.println("i = " + a.i);
a.printI();
}
}
class B {
public int i = 1;
public void printI() {}
}
//Output:
//i = 1
//print i = 2
Seems, that upcasted object has two separate "i" properties. One "i" accessible directly (a.i) and the other through methods of child class (a.printI()).
Looks like upcasted object gets properties from superclass and methods from child class.
How object can have two separate "i"s?!
Seems, that upcasted object has two separate "i" properties.
Firstly, it's worth being clear about terminology. There's no such thing as an "upcasted object" - and "i" is a field in each of A and B.
But yes, there are two separate fields here. It's not like one field "overrides" another or anything like that.
It's not clear what you were trying to achieve, but the declaration of i in A shadows the declaration of i in B. See section 6.4 of the Java Language Specification for more information.
Note that in almost all cases, fields should be private - at which point the hiding really doesn't matter, as you wouldn't try to refer to a variable which wasn't declared in the class you're coding in anyway.
That's how Java works. You have both fields "available", they just happen to have the same name. When you reference from the subclass, it is hiding the superclass' version, but it is still there.

Categories

Resources