Why variables are not behaving as same as method while Overriding.? [duplicate] - java

This question already has answers here:
why java polymorphism not work in my example
(3 answers)
Closed 6 years ago.
Generally Overriding is the concept of Re-defining the meaning of the member in the sub class.Why variables are not behaving like methods while Overriding in java ?
For instance:
class Base {
int a = 10;
void display() {
System.out.println("Inside Base :");
}
}
class Derived extends Base {
int a = 99;
#Override
// method overriding
void display() {
System.out.println("Inside Derived :");
}
}
public class NewClass {
public static void main(String... a) {
Derived d = new Derived();
Base b = d;
b.display(); // Dynamic method dispatch
System.out.println("a=" + b.a);
}
}
Since data member a is package access specified, it is also available to the Derived class. But generally while calling the overridden method using the base class reference, the method that is redefined in derived class is called (Dynamic method dispatch)..but it is not the same for the variable..why.?
EXPECTED OUTPUT
Inside Derived :
a=99
OBTAINED OUTPUT:
Inside Derived :
a=10
Prints 10 - why the variable does not behave similar to method in the derived class?
Why the variables are not allowed to be overridden in the sub class?

You typed b as an instance of Base. So when the compiler needs to resolve b.a, it looks to the definition of Base for the meaning of b.a. There is no polymorphism for instance fields.

Because the only thing that polymorphism ever applies to in Java is instance method.
Hence, you can neither override static members, nor the instance member fields. By, having these members in a derived class with the same names you're simply hiding them with a new definition.
System.out.println("a="+b.a);
Although, Base b may point to a sub-class object (at runtime) the a above has already been bound to Base class at compile time (static binding). Hence, it prints 10.

Variables behave like that because they lack behavior. In other words, variables are passive.
There is nothing about a variable's definition that a derived class can reasonably change by overriding:
It cannot change its type, because doing so may break methods of the base class;
It cannot reduce its visibility, because that would break the substitution principle.
It cannot make it final without making it useless to the base class.
Therefore, member variables declared in derived classes hide variables from the base class.

There is no way to override a class variable. You do not override class variables in Java you hide them. Overriding is for instance methods.

In this case, it might be a good idea to write a getter method:
public int getA(){
return 99;
}
Now you can override it in a derived class.

First, we don't override any class variable. Methods only.
Second, if you would like to see that the variable value has been updated or replaced, you should rather declare it as "static int" instead of "int". In this way, it will work as everybody is sharing the same variable, and the new value will be put on it.
Third, if you would like to see that the variable value being assigned and used differently, you could design it as passing a parameter in constructor, or something similar, to make it work accordingly as you desire.

The answer to this has to do with variable scoping, not polymorphism. In other words, you're overriding that variable in the class scope. So, d.a will return the variable in Derived's class scope, but b.a will return the variable in Base's class scope.

In OOP (Object Oriented Programming) the idea is to hide the data in the object and let object only communicate with invoking methods. That's why variables cannot be overloaded, in fact they are "scoped"/"attached" to a specific class.
Also the derived class should not define a again, it is already defined in the base class, so simply set a on the object to the desired value, e.g:
class Base {
private int a = 10;
public int getA() { return a; }
public void setA(inta) { this.a = a; }
}
class Derived extends Base {
// adding new variables, override methods, ...
}
// then later:
Derived d = new Derived();
d.setA(99); // override the default value 10

What would happen if variables could override other variables? Suddenly your class has to be aware of what variables the parent class is using, lest you accidentally override one and break whatever was using it in the parent class. The whole point of encapsulation is to avoid having that kind of intimate knowledge of another object's internal state. So instead, variables shadow same-named other variables, and which one you see depends on what type you're trying to reach the variable through.
There's hope, though. If all you want is to override the value, you don't have to redeclare the variable. Just change the value in an init block. If the base class is harmed by you doing that, then it chose the wrong visibility for that variable.
class Base {
int a = 10;
}
class Derived extends Base {
{ a = 99; }
}
Of course, this doesn't work very well for final variables.

we don't override any class variable. Methods only.
If you would like to see that the variable value has been updated or
replaced, you should rather declare it as "static int" instead of
"int". In this way, it will work as everybody is sharing the same
variable, and the new value will be put on it.
If you would like to see that the variable value being assigned and
used differently, you could design it as passing a parameter in
constructor, or something similar, to make it work accordingly as
you desire.
Moreover, if variables are overridden then what is left with a parent class of its own,it breaches the class security if java would give the access to change the value of variable of parent class.

Related

Can I use a non-static method in another non static method? [duplicate]

I was just reading over the text given to me in my textbook and I'm not really sure I understand what it is saying. It's basically telling me that static methods or class methods include the "modifier" keyword static. But I don't really know what that means?
Could someone please explain to me in really simple terms what Static or Class Methods are?
Also, could I get a simple explanation on what Instance methods are?
This is what they give me in the textbook:
There are important practical implications of the presence or absence of the static modifier. A public class method may be invoked and executed as soon as Java processes the definition of the class to which it belongs. That is not the case for an instance method. Before a public instance method may be invoked and executed, an instance must be created of the class to which it belongs. To use a public class method, you just need the class. On the other hand, before you can use a public instance method you must have an instance of the class.
The manner in which a static method is invoked within the definition of another method varies according to whether or not the two methods belong to the same class. In the example above, factorial and main are both methods of the MainClass class. As a result, the invocation of factorial in the definition of main simply references the method name, "factorial".
The basic paradigm in Java is that you write classes, and that those classes are instantiated. Instantiated objects (an instance of a class) have attributes associated with them (member variables) that affect their behavior; when the instance has its method executed it will refer to these variables.
However, all objects of a particular type might have behavior that is not dependent at all on member variables; these methods are best made static. By being static, no instance of the class is required to run the method.
You can do this to execute a static method:
MyClass.staticMethod(); // Simply refers to the class's static code
But to execute a non-static method, you must do this:
MyClass obj = new MyClass(); //Create an instance
obj.nonstaticMethod(); // Refer to the instance's class's code
On a deeper level the compiler, when it puts a class together, collects pointers to methods and attaches them to the class. When those methods are executed it follows the pointers and executes the code at the far end. If a class is instantiated, the created object contains a pointer to the "virtual method table", which points to the methods to be called for that particular class in the inheritance hierarchy. However, if the method is static, no "virtual method table" is needed: all calls to that method go to the exact same place in memory to execute the exact same code. For that reason, in high-performance systems it's better to use a static method if you are not reliant on instance variables.
Methods and variables that are not declared as static are known as instance methods and instance variables. To refer to instance methods and variables, you must instantiate the class first means you should create an object of that class first.For static you don't need to instantiate the class u can access the methods and variables with the class name using period sign which is in (.)
for example:
Person.staticMethod(); //accessing static method.
for non-static method you must instantiate the class.
Person person1 = new Person(); //instantiating
person1.nonStaticMethod(); //accessing non-static method.
Difference between Static methods and Instance methods
Instance method are methods which require an object of its class to be created before it can be called. Static methods are the methods in Java that can be called without creating an object of class.
Static method is declared with static keyword. Instance method is not with static keyword.
Static method means which will exist as a single copy for a class. But instance methods exist as multiple copies depending on the number of instances created for that class.
Static methods can be invoked by using class reference. Instance or non static methods are invoked by using object reference.
Static methods can’t access instance methods and instance variables directly. Instance method can access static variables and static methods directly.
Reference : geeksforgeeks
Static methods, variables belongs to the whole class, not just an object instance. A static method, variable is associated with the class as a whole rather than with specific instances of a class. Each object will share a common copy of the static methods, variables. There is only one copy per class, no matter how many objects are created from it.
Instance methods => invoked on specific instance of a specific class. Method wants to know upon which class it was invoked. The way it happens there is a invisible parameter called 'this'. Inside of 'this' we have members of instance class already set with values. 'This' is not a variable. It's a value, you cannot change it and the value is reference to the receiver of the call.
Ex: You call repairmen(instance method) to fix your TV(actual program). He comes with tools('this' parameter). He comes with specific tools needed for fixing TV and he can fix other things also.
In static methods => there is no such thing as 'this'.
Ex: The same repairman (static method). When you call him you have to specify which repairman to call(like electrician). And he will come and fix your TV only. But, he doesn't have tools to fix other things (there is no 'this' parameter).
Static methods are usually useful for operations that don't require any data from an instance of the class (from 'this') and can perform their intended purpose solely using their arguments.
In short, static methods and static variables are class level where as instance methods and instance variables are instance or object level.
This means whenever a instance or object (using new ClassName()) is created, this object will retain its own copy of instace variables. If you have five different objects of same class, you will have five different copies of the instance variables. But the static variables and methods will be the same for all those five objects. If you need something common to be used by each object created make it static. If you need a method which won't need object specific data to work, make it static. The static method will only work with static variable or will return data on the basis of passed arguments.
class A {
int a;
int b;
public void setParameters(int a, int b){
this.a = a;
this.b = b;
}
public int add(){
return this.a + this.b;
}
public static returnSum(int s1, int s2){
return (s1 + s2);
}
}
In the above example, when you call add() as:
A objA = new A();
objA.setParameters(1,2); //since it is instance method, call it using object
objA.add(); // returns 3
B objB = new B();
objB.setParameters(3,2);
objB.add(); // returns 5
//calling static method
// since it is a class level method, you can call it using class itself
A.returnSum(4,6); //returns 10
class B{
int s=8;
int t = 8;
public addition(int s,int t){
A.returnSum(s,t);//returns 16
}
}
In first class, add() will return the sum of data passed by a specific object. But the static method can be used to get the sum from any class not independent if any specific instance or object. Hence, for generic methods which only need arguments to work can be made static to keep it all DRY.
If state of a method is not supposed to be changed or its not going to use any instance variables.
You want to call method without instance.
If it only works on arguments provided to it.
Utility functions are good instance of static methods. i.e math.pow(), this function is not going to change the state for different values. So it is static.
The behavior of an object depends on the variables and the methods of that class. When we create a class we create an object for it. For static methods, we don't require them as static methods means all the objects will have the same copy so there is no need of an object.
e.g:
Myclass.get();
In instance method each object will have different behaviour so they have to call the method using the object instance.
e.g:
Myclass x = new Myclass();
x.get();
Static Methods vs Instance methods
Constructor:
const Person = function (birthYear) {
this.birthYear = birthYear;
}
Instance Method -> Available
Person.prototype.calcAge = function () {
2037 - this.birthYear);
}
Static Method -> Not available
Person.hey = function(){
console.log('Hey')
}
Class:
class PersonCl {
constructor(birthYear) {
this.birthYear = birthYear;
}
/**
* Instance Method -> Available to instances
*/
calcAge() {
console.log(2037 - this.birthYear);
}
/**
* Static method -> Not available to instances
*/
static hey() {
console.log('Static HEY ! ');
}
}
The static modifier when placed in front of a function implies that only one copy of that function exists. If the static modifier is not placed in front of the function then with every object or instance of that class a new copy of that function is made. :)
Same is the case with variables.

How is my private member getting set to null?

I have been programming java professionally for more than ten years. This is one of the weirdest bugs I've ever tried to track down. I have a private member, I initialize it and then it changes to null all by itself.
public class MyObject extends MyParent
{
private SomeOtherClass member = null;
public MyObject()
{
super();
}
public void callbackFromParentInit()
{
member = new SomeOtherClass();
System.out.println("proof member initialized: " + member);
}
public SomeOtherClass getMember()
{
System.out.println("in getMember: " + member);
return member;
}
}
Output:
proof member initialized: SomeOtherClass#2a05ad6d
in getMember: null
If you run this code, obviously it will work properly. In my actual code there are only these three occurrences (five if you count the printlns) in this exact pattern.
Have I come across some bug in the JVM? Unless I'm wrong, the parent class can't interfere with a private member, and no matter what I put between the lines of code I've shown you, I can't change the value of member without using the identifier "member".
This happens because of the order in which member variables are initialized and constructors are called.
You are calling callbackFromParentInit() from the constructor of the superclass MyParent.
When this method is called, it will set member. But after that, the subclass part of the object initialization is performed, and the initializer for member is executed, which sets member to null.
See, for example:
What's wrong with overridable method calls in constructors?
State of Derived class object when Base class constructor calls overridden method in Java
Using abstract init() function in abstract class's constructor
In what order constructors are called and fields are initialized is described in paragraph 12.5 of the Java Language Specification.
Assignment of null to field member happens after executing parent constructor.
The fix is to change:
private SomeOtherClass member = null;
to:
private SomeOtherClass member;
Never, never ever call a non final method from the superclass' constructor.
It's considered bad practice, precisely because it can lead to nasty, hard-to-debug errors like the one you're suffering.
Perform initialization of a class X within X's constructor. Don't rely on java's initialization order for hierarchies. If you can't initialize the class property i.e. because it has dependencies, use either the builder or the factory pattern.
Here, the subclass is resetting the attribute member to null, due to superclass and subclass constructors and initializer block execution order, in which, as already mentioned, you shouldn't rely.
Please refer to this related question for concepts regarding constructors, hierarchies and implicit escaping of the this reference.
I can only think about sticking to a (maybe incomplete) set of rules/principles to avoid this problem and others alike:
Only call private methods from within the constructor
If you like adrenaline and want to call protected methods from within the constructor, do it, but declare these methods as final, so that they cannot be overriden by subclasses
Never create inner classes in the constructor, either anonymous, local, static or non-static
In the constructor, don't pass this directly as an argument to anything
Avoid any transitive combination of the rules above, i.e. don't create an anonymous inner class in a private or protected final method that is invoked from within the constructor
Use the constructor to just construct an instance of the class, and let it only initialize attributes of the class, either with default values or with provided arguments

Effect of hiding in polymorphism [duplicate]

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.

method overriding

class A
{
int i=10;
void show()
{
System.out.println("class A");
}
}
class B extends A
{
int i=5;
public void show()
{
System.out.println("class B");
}
}
class M
{
public static void main(String s[])
{
A a=new B();
a.show();
System.out.println(a.i);
}
}
OUTPUT= class B
10
If class A method is overridden by class B method then why not the variable 'i'?
Because variables are not virtual, only methods are.
It is not overwritten, but hidden. In your output you specifically requested the value of a.i, not ((B)a).i.
This is a "feature" of the implementation. In memory, this looks like so:
a:
pointer to class A
int i
b:
pointer to class B
int i (from A)
int i (from B)
When you access i in an instance of B, Java needs to know which variable you mean. It must allocate both since methods from class A will want to access their own field i while methods from B will want their own i (since you chose to create a new field i in B instead of making A.i visible in B). This means there are two i and the standard visibility rules apply: Whichever is closer will win.
Now you say A a=new B(); and that's a bit tricky because it tells Java "treat the result from the right hand side as if it were an instance of A".
When you call a method, Java follows the pointer to the class (first thing in the object in memory). There, it finds a list of methods. Methods overwrite each other, so when it looks for the method show(), it will find the one defined in B. This makes method access fast: You can simply merge all visible methods in the (internal) method list of class B and each call will mean a single access to that list. You don't need to search all classes upwards for a match.
Field access is similar. Java doesn't like searching. So when you say B b = new B();, b.i is obviously from B. But you said A a = new B() telling Java that you prefer to treat the new instance as something of type A. Java, lazy as it is, looks into A, finds a field i, checks that you can see that field and doesn't even bother to look at the real type of a anymore (because that would a) be slow and b) would effectively prevent you from accessing both i fields by casting).
So in the end, this is because Java optimizes the field and method lookup.
Why no field overrides in Java though?
Well, because instance field lookups in Java happen at compile time: Java simply gives you the value of the field at a given offset in object's memory (based on the type information at hand during compilation: in this case a is declared to be of type A).
void foo() {
A a = new B();
int val = a.i; // compiler uses type A to compute the field offset
}
One may ask "Why didn't compiler use type B since it knows that a is in fact an instance of B? Isn't it obvious from the assignment just above?". Of course, in the case above, it's relatively obvious and compiler may try to be smarter and figure it out.
But that's compiler design "rat hole", what if a "trickier" piece of code is encountered, like so:
void foo(A a) {
int val = a.i;
}
If compiler were "smarter", it would become its job to look at all invocations of foo() and see what real type was used, which is an impossible job since compiler can not predict what other crazy things may be passed to foo() by unknown or yet unwritten callers.
It's a design decision by the developers of Java, and is documented in the Java Language Specification.
A method with the same method signature as a method in its parent class overrides the method in its parent class.
A variable with the same name as a variable in its parent class hides the parent's variable.
The difference is that hidden values can be accessed by casting the variable to its parent type, while overridden methods will always execute the child class's method.
As others have noted, in C++ and C#, to get the same override behavior as Java, the methods need to be declared virtual.
a is an instance of A. You call the constructor B(). But it is still a A class.
That is why i equals 10;
The override from the method will be succeded.
Note a class starts not with
public class A()
but with;
public class A { ... }
Tip: You can use setters and getters to make sure of what data-members you use.
Or: You simply can set the values at the constructor instead of the class declaration.
Because by default the variables are private. You must declare it as "protected", then will be properly inherited.

inheritance and class members

GIVEN:
class A
{
String s = "A";
}
class B extends A
{
String s = "B";
}
public class C
{
public static void main(String[] args){ new C().go();}
void go()
{
A a = new B();
System.out.println(a.s);
}
}
Question:
What are the mechanics behind JVM when this code is run? How come a.s prints back as "A".
Field references are not subject to polymorphism, so at compile time the compiler is referencing A's field because your local variable is of type A.
In other words, the field behavior is like the Java overloading behavior on methods, not the Java overriding behavior.
You probably expect fields to be overridden like method, with dynamic dispatch based on the runtime type of the object.
That's not how Java works. Fields are not overridden, they are hidden. That means an object of class B has two fields named "s", but which of them is accessed depends on the context.
As for why this is so: it wouldn't really make sense to override fields, since there is no useful way to make it work when the types are different, and simply no point when the type is the same (as you can just use the superclass field). Personally, I think it should simply be a compiler error.
This isn't polymorphism (as tagged).
Java has virtual methods, not virtual member variables - i.e. you don't override a property - you hide it.
Although member variables are inherited from a base class, they are not invoked polymorphically (i.e dynamic invocation does not apply to member variables).
So, a.s will refer to the member in the base class and not the derived class.
Having said that, the code is not following OO principles. The members of a class need to be private/protected (not public or default) depending on the business use case and you need to provide public methods to get and set the values of the member.

Categories

Resources