nimbudew
nimbudew

Reputation: 978

Java virtual method invocation

Say I have the following code:

public class Employee
{
    public int salary = 2000;
    public void getDetails() {...}
}

public class Manager extends Employee
{
    public int salary = 5000;
    public int allowance = 8000;
    public void getDetails() {...}
}

and a main() that does the following:

Employee emp = new Employee();
Manager man = new Manager();
emp.getDetails(); // method of Employee called, output ok.
man.getDetails(); // method of Manager called, output ok.

Employee emp_new = new Manager();
emp_new.getDetails(); // method of Manager called, ok.
System.out.println(emp_new.allowance); // problem, as Employee doesn't know about allowance. Ok

// the problem
System.out.println(emp_new.salary); // why 2000 and not 5000?

The book says "you get the behavior associated with the object to which the variable refers at runtime". Ok, I get behavior of Manager class when a method getDetails is called, but when I access an attribute salary, I get behavior of variable and not the object. Why is that?

Upvotes: 4

Views: 1244

Answers (4)

Raúl
Raúl

Reputation: 1552

Because this is NOT Virtual Method Invocation.

As quoted:

you get the behavior associated with the object to which the variable refers at runtime

You overlooked that the variable salary IS NOT part of behavior - it is state of Object.

Upvotes: 0

Sumit Singh
Sumit Singh

Reputation: 15886

This behavior is because of hiding of fields.

From JLS 8.3. Field Declarations

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.

In this respect, hiding of fields differs from hiding of methods (§8.4.8.3), for there is no distinction drawn between static and non-static fields in field hiding whereas a distinction is drawn between static and non-static methods in method hiding.

A hidden field can be accessed by using a qualified name (§6.5.6.2) if it is static, or by using a field access expression that contains the keyword super (§15.11.2) or a cast to a superclass type.

So in your case you are accessing hidden variable salary directly by using reference variable of Employee class to store object of Manager (casting to a superclass type).

So it will print Employee hidden salary rather Employeeclass salary.

Upvotes: 2

Eran
Eran

Reputation: 393791

There's no polymorphism of fields. A field in a sub-class hides a field with the same name in the super-class, but if you use a variable of the super-class type - Employee - to access the field, you get the field of the super-class.

I don't see the point in declaring fields having the same name in both the super-class and the sub-class. If the sub-class has access to the field of the super-class, it shouldn't declare a field of the same name.

If you must declare a field of the same name in both super-class and sub-class, you can achieve polymorphism by accessing the field via getter and setter methods. You can override the getter and setter methods in the sub-class, so that they access the field of the sub-class instead of the field of the super-class.

public class Employee
{
    private int salary = 2000;
    public void getSalary() {
        return salary;
    }
}

public class Manager extends Employee
{
    private int salary = 5000;
    @Override
    public void getSalary () {
        return salary;
    }
}

...

Employee emp_new = new Manager();
System.out.println(emp_new.getSalary()); // will print 5000

Upvotes: 6

Danyal Sandeelo
Danyal Sandeelo

Reputation: 12391

The Employee class is the parent class and the attributes that are called would return the value of parent attributes (as they have the same name and type).

Upvotes: 0

Related Questions