Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Polymorphism with instance variables [duplicate]

Here are three classes that I wrote:

public class Shape {

    public int x = 0;

    public void getArea() {
        System.out.println("I don't know my area!");
    }

    public String toString() {
        return "I am a shape!";
    }

    public int getX() {
        return x;
    }
}

public class Rectangle extends Shape {

    public int x = 1;

    public int getX() {
        return x;
    }

    public void getArea() {
        System.out.println("L*W");
    }

    public String toString() {
        return "I am a rectangle!";
    }
}

public class Tester {

    public static void main(String[] args) {
        Shape s = new Shape();
        Rectangle r = new Rectangle();

        System.out.println(r);
        System.out.println(r.x + "\n");

        s = r;
        System.out.println(s);
        s.getArea();
        System.out.println(s.x);
        System.out.println(s.getX());
    }
}

The output from the main method of the Tester class is:

I am a rectangle!

1

I am a rectangle!

L*W

0

1

Why does s.x return 0 and not 1? As isn't the current instance of the variable a Rectangle and that class also has that same instance variable declared, or does the variable in the Rectangle class not override the previous public x variable in the Shape class as it does to the getX() method in the rectangle class thus returning 1?

Also as a general rule the superclass has access to the implementation of the its subclasses methods only if they are declared in that class as well? Is this because the compiler will see that the same amount of methods with the same signature are in the "Shape" class (with overridden Rectangle implementations) and accept those as valid Shape methods?

Thanks in advance,

like image 877
PragmaticProgrammer Avatar asked Mar 20 '13 01:03

PragmaticProgrammer


People also ask

Can we override instance variables?

Because instance variables CANNOT be overridden in Java. In Java, only methods can be overridden. When you declare a field with the same name as an existing field in a superclass, the new field hides the existing field. The existing field from the superclass is still present in the subclass, and can even be used ...

Are instance variables inherited in Java?

I know that instance variable are not inherited but they can be accessed in sub class. If they can be accessed in sub class then does that means that they are shared between super class and subclass or both super class and subclass have different copy.

Are variables polymorphic in Java?

A variable is called polymorphic if it refers to different values under different conditions. Object variables (instance variables) represent the behavior of polymorphic variables in Java. It is because object variables of a class can refer to objects of its class as well as objects of its subclasses.

What is instancing in Java?

What is instance variable in Java? Instance variables in Java are non-static variables which are defined in a class outside any method, constructor or a block. Each instantiated object of the class has a separate copy or instance of that variable. An instance variable belongs to a class.


1 Answers

There is no polymorphism for fields in Java. There is however, inheritance. What you've effectively done is create two fields in your Rectangle class, with the same name. The names of the field are, effectively:

public class Rectangle {
    public int Shape.x;
    public int Rectangle.x;
}

The above doesn't represent valid Java, its just an illustration of how the fields are scoped in your class

Within the entire scope of the Rectangle class, the superclass field of the same name is hidden. So anytime you reference the simple name x, or the scoped name this.x, within the class, you are referring to the field that is defined in Rectangle. You can actually access the superclass field as well, with the scoped name super.x.

Now, from outside of the class, the rules for which field is being accessed is slightly different. The scope will be determined by the compile time type of the class that the field is being referenced from. So in your code:

Shape s = new Shape();
Rectangle r = new Rectangle();

s = r;
System.out.println(s.x);

The output is 0 because the compile time type of s is Shape (not Rectangle). You can observe a change in this behavior when you do this:

Shape s = new Shape();
Rectangle r = new Rectangle();

s = r;
System.out.println(((Rectangle)s).x);

Presto! Your output is now 1, because the compiler sees that you've scoped the field access to Rectangle.

To condense the rules of visibility:

You can read more about instance variable hiding in the JLS, Section 8.3.3.2

like image 145
Perception Avatar answered Sep 20 '22 22:09

Perception