I'm training for a Java exam, and I've come across something I don't understand in last year subject. Here is the code
class Mother {
int var = 2;
int getVar() {
return var;
}
}
class Daughter extends Mother {
int var = 1;
int getVar() {
return var;
}
public static void main(String[] args) {
Mother m = new Mother();
System.out.println(m.var);
System.out.println(m.getVar());
m = new Daughter();
System.out.println(m.var);
System.out.println(m.getVar());
}
}
The question is "what is the output of this program?". I would have go with 2 2 1 1, but when compiling and running this piece of code, I get 2 2 2 1.
Anyone can explain me why ?
Thanks for reading !
The method call m.getVar() is a virtual method call. The second time you call it, it's dynamically dispatched to the derived Daughter.getVar(), which does what you expect (accesses Daugther.var and returns that).
There is no such virtual dispatch mechanism for member fields. So m.var always refers to Mother.var, i.e. the base class's version of that variable.
The Daughter class can be seen as having two different var member: the one from Mother and its own. Its own member "hides" the one in Mother, but can be accessed from within the Daughter class by using super.var.
The official spec for this is in section 8.3 Field Declarations of the JLS.
Quote:
If the class declares a field with a certain name, then the declaration of that field is said to hide any and all accessible declarations of fields with the same name in superclasses, and superinterfaces of the class. The field declaration also shadows (§6.3.1) declarations of any accessible fields in enclosing classes or interfaces, and any local variables, formal method parameters, and exception handler parameters with the same name in any enclosing blocks.
Note that it can get pretty interesting (emphasis added):
If a field declaration hides the declaration of another field, the two fields need not have the same type.
And:
There might be several paths by which the same field declaration might be inherited from an interface. In such a situation, the field is considered to be inherited only once, and it may be referred to by its simple name without ambiguity.
So that paragraph is well worth reading :-)
Focus on these lines:
Mother m;
m = new Daughter();
System.out.println(m.var);
System.out.println(m.getVar());
You are constructing a Daughter object, but you are treating it like it's base class Mother. So when you access m.var you are accessing the base class variable var. Meanwhile when you call a method, even if you are referring to the base class reference, the overrided method is called.
It's a different behavior for methods and fields.. Fields reference cannot be overrided.
Methods can be overridden however fields can only be hidden. The difference is that a non-static method uses the type of the object referenced, a field takes the type of the reference. You see a similar thing with static methods which only be hidden where the class of the "reference" and the object (if provided) is ignored.
For your interest, try giving the fields different types. ;)
You can also try
System.out.println(((Mother)m).var); // uses var in Mother
System.out.println(((Daughter)m).var); // uses var in Daughter
m = new Daughter();
Though you have created a daughter object, you are referring that object with Mother m reference. So, any call using m will call the Mother class members, not daughter's
I ran this in Eclipse and checked the values with debugger, the debugger actually shows the local m -variable having TWO different var -members after the m = new Daugher() -line with values 2 and 1. m.var seems to resolve to the one in Mother, and the m.getVar() calls the getVar in Daughter (as expected).
However, when I change the main-method to look like this:
Mother m = new Mother();
System.out.println(m.var);
System.out.println(m.getVar());
Daughter d = new Daughter();
System.out.println(d.var);
System.out.println(d.getVar());
It actually outputs 2, 2, 1, 1, so it would seem that the declaration of the variable affects which class's var is used.
I read the answers and non of them (so far) gave good reason why in Object oriented language as Java is, this should be the case. I will try to explain.
Suppose that you have function that takes Mother as arg:
void foo(Mother m) {
print(m.var);
}
This function (actually the compiler) has no idea if you will call it with Mother, Daughter or with another Dauther2 that doesn't even have var variable declared. Because of that, when the reference is of type Mother, reference to a member variable must be linked (by the compiler) to the Mother's member. The similar applies to function too, so the functions are linked to Mother's declaration of getVar(), but not to Mother's implementation of getVar()
So, member variables are always linked (by the compiler) based on the reference. Another way to explain it: If you remove Mother's var (and make Mother's getVar() compilable), your second m.var (when m refers to Daughter) won't compile even Daughter has member var.
I hope i was clear.
Related
I was having an exam in Java today and the examiner asked me if I can provide any examples of using polymorphism in my Spring Boot project.
As I couldn`t think of anything at first, he pointed out that I have overriden toString() in my models and that this is dynamic/runtime polymorphism.
However, I am not sure that I understand his point, because to my understanding, a behavior is considered polymorphmic when we have a parent class reference variable pointing to a subclass object (focusing on dynamic polymorphism).
Then at runtime the actual object, to which the parent class variable points to, is fetched and its method is called, as explained nicely here.
However, I do not use upcasting in my project (i.e. initializing my POJO classes with an Object class variable).
Thus, my question is - is overriding toString() considered polymorphism, although the parent class (Object) is never used as a reference variable?
All exampes of runtime polymorphism that I find on Stackoverflow, including the ones here and this one with toString, illustrate a situation where we have a parent class variable pointing to a subclass object, e.g:
Object object = new User("petar");
String name = object.toString(); // assign to variable for clarity`s sake
System.out.println(name);
// prints petar
Where my User class is:
public class User {
String name;
public User(String name) {
this.name = name;
}
public String toString() {
return name;
}
}
However, in my project I simply create users and other POJO classes with their own reference variables, e.g:
User user = new User("petar");
String name = user.toString();
System.out.println(name);
// prints petar, as toString is overriden
Is the above considered polymorphism, although there is no upcasting / parent reference variable involved?
My classmate argues that it is, because for non-final instance methods, the compiler doesn`t know which method to call - it only ensures that there is such method in the superclass, so it prolongs this decision up until runtime (late binding) by inserting an instruction into the compiled code, which is checked then and the actual object, to which the variable points to, is fetched, and its method is called (source).
However, in this article it is stated that:
Method Overriding is an example of runtime polymorphism. When a parent
class reference points to the child class object then the call to the
overridden method is determined at runtime, because during method call
which method(parent class or child class) is to be executed is
determined by the type of object. This process in which call to the
overridden method is resolved at runtime is known as dynamic method
dispatch.
So: is method overriding sufficient for polymorphism, or is it a requirement that there is a parent class reference to the subclass object? Am I safe to say at interviews that merely overriding toString() is an example of polymorphism?
Thanks to the comments and a few other sources, I believe I can now answer my question as follows:
One could argue that overriding toString() is an example of polymorphism because:
The Java Virtual Machine (JVM) always selects the method to invoke on non-final instance methods based on the object that it is referenced to, and not the method defined by the variable type. This is known as dynamic method invocation or late binding i.e - the decision which method to call happens at runtime, hence the wording "runtime" polymorphism. Source: Oracle Docs, JavaWorld.
Thus, regardless whether we consciously use polymorphism by e.g. programming to interfaces or we do a simple toString() method override, but still continue to use our classes with their own class variables (i.e. using a "User" variable instead of the parent class "Object" variable), a decision about which method to call is always made on runtime by checking the type of object our variables are referring to.
Thus, the evaluation on which model to call (i.e. the polimorphic behavior) happens, regardless which of the two initializations we use:
User user = new User("username1");
System.out.println(user);
// or
Object object = new User("username1");
System.out.println(object);
The type of the variable is insignificant for our question, what matters is the object that it is referring to, and which of all possible objects it refers to (i.e a parent or a child), is decided on runtime.
The type of the variable is only relevant to either limit the scope of available methods to the ones in the parent class and potentially overridden by its children (if we use a parent class reference variable) or to gain access to the specific methods of the child (if we use a child class reference variable).
For example, if we added a new method to our User class:
public String instanceMethod () {
return "User instance method called";
}
It would not be available through a Object class variable:
It would only be available through a User class variable.
Hope this clears the confusion for everyone else that needs a more detailed explanation too.
I'm wondering why Java has this strange behavior regarding a superclass and a subclass having instance variables with the same name.
Let's say we have the following class definitions:
class Parent {
int var = 1;
}
class Child extends Parent {
int var = 2;
}
By doing this, we are supposed to have hidden the superclass's variable var. And if we do not explicitly specify a way to access Parent's var via a super call, then we should never be able to access var from an instance of a child.
But when we have a cast, this hiding mechanism breaks:
Child child = new Child();
Parent parent = (Parent)child;
System.out.println(parent.var); // prints out 1, instead of 2
Doesn't this completely circumvent the whole point of field hiding? If this is the case, then doesn't that render the the idea completely useless?
EDIT: I am referring specifically to this article in the Java Tutorials. It mentions
Within the subclass, the field in the superclass cannot be referenced
by its simple name. Instead, the field must be accessed through super...
From what I read there, it seems to imply that the developers of Java had some kind of technique in mind in doing this. Though I agree that it is a rather obscure concept and would probably bad practice in general.
In Java, data members are not polymorphic. This means that Parent.var and Child.var are two distinct variables that happen to have the same name. You're not in any sense "overriding" var in the derived class; as you have discovered yourself, both variables can be accessed independently of one another.
The best way forward really depends on what you're trying to achieve:
If Parent.var should not be visible to Child, make it private.
If Parent.var and Child.var are two logically distinct variables, give them different names to avoid confusion.
If Parent.var and Child.var are logically the same variable, then use one data member for them.
The "point" of field hiding is merely to specify the behaviour of code which does give a variable the same name as one in its superclass.
It's not meant to be used as a technique to genuinely hide information. That's done by making the variables private to start with... I would strongly recommend using private variables in virtually all cases. Fields are an implementation detail which should be hidden from all other code.
Attributes are not polymorphic in Java, and anyway declaring a public attribute is not always a good idea. For the behavior you're looking for, it's better to use private attributes and accessor methods, like this:
class Parent {
private int var = 1;
public int getVar() {
return var;
}
public void setVar(int var) {
this.var = var;
}
}
class Child extends Parent {
private int var = 2;
public int getVar() {
return var;
}
public void setVar(int var) {
this.var = var;
}
}
And now, when testing it, we get the desired result, 2:
Child child = new Child();
Parent parent = (Parent)child;
System.out.println(parent.getVar());
This scenario is known as variable hiding, When the child and parent class both have a variable with the same name, child class's variable hides parent class's variable and this process is called variable hiding.
In Java variables are not polymorphic and Variable Hiding is not same as Method Overriding
While variable hiding looks like overriding a variable similar to method overriding but it is not, Overriding is applicable only to methods while hiding is applicable variables.
In the case of method overriding, overridden methods completely replaces the inherited methods so when we try to access the method from parent's reference by holding child's object, the method from child class gets called.
But in variable hiding child class hides the inherited variables instead of replacing, so when we try to access the variable from parent's reference by holding child's object, it will be accessed from the parent class.
public static void main(String[] args) throws Exception {
Parent parent = new Parent();
parent.printInstanceVariable(); // Output - "Parent`s Instance Variable"
System.out.println(parent.x); // Output - "Parent`s Instance Variable"
Child child = new Child();
child.printInstanceVariable();// Output - "Child`s Instance Variable, Parent`s Instance Variable"
System.out.println(child.x);// Output - "Child`s Instance Variable"
parent = child; // Or parent = new Child();
parent.printInstanceVariable();// Output - "Child`s Instance Variable, Parent`s Instance Variable"
System.out.println(parent.x);// Output - Parent`s Instance Variable
// Accessing child's variable from parent's reference by type casting
System.out.println(((Child) parent).x);// Output - "Child`s Instance Variable"
}
As we can see in above when an instance variable in a subclass has the same name as an instance variable in a superclass, then the instance variable is chosen from the reference type.
Declaring variables with the same name in both child and parent create confusion we should always avoid it so there will be no confusion. And this is why we should also always stick to General Guidelines to create POJOs and declare our variables with private access and also provide proper get/set methods to access them.
You can read more on my article What is Variable Shadowing and Hiding in Java.
When you are casting, you effectively tell the compiler "I know better" - it suspends the normal strong-typing inference rules and gives you the benefit of a doubt.
By saying Parent parent = (Parent)child; you are telling the compiler "treat this object as if it were an instance of Parent".
On another note, you are confusing "information hiding" principle of OO (good!) with a field-hiding side-effect (usually bad).
As you pointed out:
we are supposed to have hidden the superclass's variable var
The main point here is Variables do not override as methods do, so when you call directly Child.var you are calling a variable directly from the Child class and when you call Parent.var you're calling a variable from the Parent class, no matter if they do have the same name.
As a side note I would say this is really confusing and shouldn't be allowed as valid syntax.
I had done a bit of Python long back. I am however moving over to Java now. I wanted to know if there were any differences between the Python "self" method and Java "this".
I know that "self" is not a keyword while "this" is. And that is pretty much what I could figure out. Am I missing anything else?
First of all, let me correct you - self is not a method. Moving further:
Technically both self and this are used for the same thing. They are used to access the variable associated with the current instance. Only difference is, you have to include self explicitly as first parameter to an instance method in Python, whereas this is not the case with Java. Moreover, the name self can be anything. It's not a keyword, as you already know. you can even change it to this, and it will work fine. But people like to use self, as it has now become a bit of a convention.
Here's a simple instance method accessing an instance variable in both Python and Java:
Python:
class Circle(object):
def __init__(self, radius):
# declare and initialize an instance variable
self.radius = radius
# Create object. Notice how you are passing only a single argument.
# The object reference is implicitly bound to `self` parameter of `__init__` method
circle1 = Circle(5);
Java:
class Circle {
private int radius;
public Circle(int radius) {
this.radius = radius;
}
}
Circle circle1 = new Circle(5);
See also:
Wiki page of this
About self in Python (here is the source: Python self explanation):
The reason you need to use self. is because Python does not use the # syntax to refer to instance attributes. Python decided to do methods in a way that makes the instance to which the method belongs be passed automatically, but not received automatically: the first parameter of methods is the instance the method is called on. That makes methods entirely the same as functions, and leaves the actual name to use up to you (although self is the convention, and people will generally frown at you when you use something else.) self is not special to the code, it's just another object.
Python could have done something else to distinguish normal names from attributes -- special syntax like Ruby has, or requiring declarations like C++ and Java do, or perhaps something yet more different -- but it didn't. Python's all for making things explicit, making it obvious what's what, and although it doesn't do it entirely everywhere, it does do it for instance attributes. That's why assigning to an instance attribute needs to know what instance to assign to, and that's why it needs self..
About this in Java being explained by Oracle (here is the source: Java this explanation):
Within an instance method or a constructor, this is a reference to the current object — the object whose method or constructor is being called. You can refer to any member of the current object from within an instance method or a constructor by using this.
The most common reason for using the this keyword is because a field is shadowed by a method or constructor parameter.
Be careful super can keep its own version of this.i in Java, but self.i always refer to the child in Python.
Main.java:
class Parent {
int i;
Parent() {
this.i = 5;
}
void doStuff() {
System.out.println(this.i);
}
}
class Child extends Parent {
int i;
Child() {
this.i = 7;
}
}
class Main {
public static void main(String[] args) {
Child m = new Child();
System.out.println(m.i); //print 7
m.doStuff(); //print 5
}
}
Main.py:
class Parent(object):
i = 5;
def __init__(self):
self.i = 5
def doStuff(self):
print(self.i)
class Child(Parent, object):
def __init__(self):
super(Child, self).__init__()
self.i = 7
class Main():
def main(self):
m = Child()
print(m.i) #print 7
m.doStuff() #print 7
m = Main()
m.main()
Output:
$ java Main
7
5
$ python Main.py
7
7
[Update]
The reason is because Java's int i declaration in Child class makes the i become class scope variable, while no such variable shadowing in Python subclassing. If you remove int i in Child class of Java, it will print 7 and 7 too.
From my perspective, the most obvious difference is that in java class, in the constructor, you need to specify the field
this.radius = radius
While in the python code, you don't have to do so, it's implicit.
This question already has answers here:
Slight confusion regarding overriding where variables are concerned
(6 answers)
Closed 9 years ago.
I am having some doubts about this Java code. The output it gives is "furry bray". My questions:
Why do i get this output?
How can I access the String object reference "name" in ZooKeeper class?
If it has something to do with variable shadowing, then which variable is being shadowed?
Code:
class Mammal {
String name = "furry ";
String makeNoise() { return "generic noise"; }
}
class Zebra extends Mammal {
String name = "stripes ";
String makeNoise() { return "bray"; }
}
public class ZooKeeper {
public static void main(String[] args) { new ZooKeeper().go(); }
void go() {
Mammal m = new Zebra();
System.out.println(m.name + m.makeNoise());
//Output comes as "furry bray". Please explain this.
//And how can we access the name variable, the one having "stripes " in it.
//Does it have something to do with Variable Shadowing?
}
}
Variables aren't polymorphic. When you access m.name, that will always use the Mammal.name field which is part of that object, regardless of the execution-time type of the object. If you need to get access to Zebra.name, you need an expression with a compile-time type of Zebra.
The makeNoise method is called virtually though - the implementation used at execution time does depend on the type of the object.
Note that if you make all your fields private - which is generally a good idea anyway - this doesn't end up being an issue.
This is actually hiding rather than shadowing. See JLS section 8.3 for details on hiding, and section 6.4.1 for shadowing. I can't say that I always keep the differences straight...
Output comes as "furry bray". Please explain this.
fields in java programs are not accessed via dynamic lookup. Instead they are resolved statically while compile time. That's why you are getting furry for m.name. Whereas, methods in java programs are accessed via dynamic lookup. That's why you are getting bray for m.makeNoise().
And how can we access the name variable, the one having "stripes " in
it?
And if you want to access Zebra.name , you should type cast m to 'Zebra'.This would look like this:
System.out.println(((Zebra)m).name + m.makeNoise());
UPDATE
The phenomena that is exhibiting here is the result of Fields Hiding rather than variable shadowing.
There is no variable overriding in Java, you declared name in both the parent and the child but you referred to it through a parent reference variable. That's why you got 'furry'.
There is overriding for methods, which is why you got bray. Because on runtime it looked at the real object in the heap and saw it's a Zebra.
Variable names in Java are resolved by the reference type, not the object they are referencing. So, m.name refers to the variable name in Mammal even dough m is a Zebra.
It happened because your field name from Mammal is just hidden by name field from Zebra. You can then access it simply by casting to required type.
On the other side makeNoise() method overrides same method from parent so you can't access implementation from parent anymore.
I can't seem to understand the static key word (java) so I googled it up and viewed a thread in this website, though I'm sure the answer was conclusive and clear -it always is over here- I didn't seem to understand it for two reasons; I'm not a native English speaker and the language was a bit vague for me, and it lacked exemples of use in classes, instance of classes, interfaces (if possible), instance of interfaces and variables, lists and arrays ect.
I would really appreciate any help and please keep the English as simple as possible ;)
Thank you
Aditsan
Note from editor: Please note that the original poster is asking for examples, and is not a native English speaker as you provide answers. From the comments, it appears that OP doesn't understand the concept well enough to ask about the parts that don't make sense yet, so examples would be awesome! It may take extra details and multiple different explanations to find the combination of answers that works best.
I think it helps to understand what non-static means, i.e. field/methods/... that are declared without the keyword static.
Every field declared without the keyword static exists as part of an object. If you have two objects, each of these two objects has a field with possibly different contents:
class X {
int f;
}
X x1 = new X();
X x2 = new X();
x1.f = 5;
x2.f = 10;
// x1.f still is 5
However, static fields exist not per object, but per class. So in the following example, there is only one field g no matter how many (if any!) objects of class Y you have:
class Y {
static int g;
}
Y y1 = new Y();
Y y2 = new Y();
y1.g = 5;
y2.g = 10;
// y1.g is 10, because y1.g and y2.g mean the exact same thing
I personally think accesses to static fields should be made using the class (Y.g) instead of mentioning object instances (y1.g), so that the existence without any object instance is more explicit.
For methods the difference is that non-static methods are associated to an object instance, which can be accesses using this inside the method. When invoking a method declared with void m() you can access non-static (and static) fields of the object it is invoked on (so for x1.m() from the example above you can get to the field containing 5, for x2.m() you can access the field containing 10.
Static methods, however, can be invoked without having a (corresponding?) object around. If the declaration is static void n() inside class Y, you can call this method using Y.n() or y1.n() (if y1 is an instanceof Y, as above). Here, too, I prefer the first way of writing it down. Because in static methods you do not have a reference to the object instance (which is named this in non-static methods), you cannot access specific non-static fields from inside a static method - simply because there is no clear association to a specific object.
Regarding static and class definitions: This is rather advanced. You can declare a class inside another class. If the inner class is not static, every object instance of the inner class also has a reference to an instance of the outer class (which also means that you only can create an instance of the inner class if you have an instance of the outer class). This is not always what you want. By declaring the inner class static it just exists and can be used, more or less, like a class defined in its own file.
Basically, static implies/provides two things:
1) Only one instance of an "item" exists in the whole system (JVM)
2) Static "items" are also context/state free
To explain (1) above: Suppose you have a Meal Token issuer. No matter how many users/processes are there in the system, all tokens must be issued by a single "thing". You would develop that "thing" as static. You would then decide what that "thing" is. It could be a class that does a complex operation and implements a complex business rule. Then you would have a single static class issuing tokens in "a single uniform way" for the whole system. Some times, all that matters is that the token should be "static" but how it is issued could be non-static. Then you would simply implement a "Static" token counter.
To explain (2) : Going by what is said for (1) above, you can easily see why it is important that the static "things" operate in a context-free manner. That is, they do not know who calls them or for what purpose. When they are called, they do not borrow anything from the past, they need all inputs from the current caller, and they just do their job, and remember nothing for the future.