Vivyen
Vivyen

Reputation: 85

Non overridden method doesn't show subclass field

class Parent {
    String st = "external";

    void print() {
        System.out.println(st); 
        System.out.println(this.st);
    }
}

class Child extends Parent {
    String st = "inner";
}

public static void main(String[] args) {
    new Child().print(); // shows "external"
}

Why does print() called on subclass not show the string "inner"?

Upvotes: 1

Views: 97

Answers (4)

Ironcache
Ironcache

Reputation: 1759

The other answers cover why the behavior you notice is expected, so I won't touch on that. In terms of a solution to your problem, there are a few worth mention (neglecting things like reflection and subclass casting; technically solutions, but poor ones).

Option 1: Set Parameter

As Will mentioned, can simply set the parameter in Child:

class Child extends Parent{
    public Child() {
        st = "inner";
    }
}

Option 2: Method Override

Can also override the print() method (because, as mentioned, only methods can be overridden). Child would become something along the lines of:

class Child extends Parent{
    ...

    @Override
    void print() {
        // Child-specific implementation here.
    }
}

This will result in Child objects using their print method in place of Parent's method.

Option 3: Strategy Pattern

Another option is to use Strategy pattern. Consider the following:

public interface Strategy {
    String getString();
}

public class ParentStrategy implements Strategy {
    @Override
    public String getString() {
        return "external";
    }
}

public class ChildStrategy implements Strategy {
    @Override
    public String getString() {
        return "inner";
    }   
}

From here, all you need to do is change your Parent object so that it defaults to ParentStrategy, provide accessors to change the Strategy, change its print method to use the getString() method of its Strategy object, and change the Strategy in Child to use ChildStrategy:

class Parent{
    Strategy strat = new ParentStrategy();

    void setStrategy(Strategy s) {
        strat = s;
    }

    void print() {
        System.out.println(strat.getString()); 
    }
}
class Child extends Parent{
    public Child() {
        super();
        setStrategy(new ChildStrategy());
    }
}

In real world applications, this pattern is a fundamental tool to making flexible applications.

Upvotes: 0

Willi Mentzel
Willi Mentzel

Reputation: 29844

As the others mentioned the field st of the Parent class is hidden. Just an addition if you want it to print "inner".

Change Child class to this:

class Child extends Parent {
    public Child() {
        st = "inner";
    }
}

This way the value of st from the Parent class is overriden!

Upvotes: 1

Jesper
Jesper

Reputation: 206796

why print() called on subclass doesn't show string - "inner" ?

Because member variables cannot be overridden. The member variable st in class Child does not override the member variable st in class Parent. The two member variables are two separate variables, which happen to have the same name.

The methods in class Parent see the member variable st that is defined in class Parent, and not the one in class Child, even if the object is really an instance of class Child.

Only methods can be overridden.

More information in Oracle's Java Tutorials: Hiding Fields (thanks @JonK).

Upvotes: 2

why print() called on subclass doesn't show string - "inner" ?

why should it? you are calling the method print() that is only override in the parent class up there in the parent class st is only holding the value "external"

Upvotes: 0

Related Questions