Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java field hiding for attributes

Tags:

java

field

I just started to learn Java, so please bear with me if the answer is somewhat obvious. I did some research but no avail.

From what I understand, attributes are not overriden but only field hidden. To determine whether the attribute in the superclass or the subclass is used, Java will check the type of the reference.

Then I don't under stand the output here:

public class Super {
    String str = "I'm super!\n";

    public String toString() {
        return str;
    }
}

public class Sub extends Super {
    String str = "I'm sub.\n";
}

public class TestFH {
    public static void main(String[] args) {
        Sub s1 = new Sub();

        System.out.printf(s1.toString());
    }
}

It gives me:

I'm super!

I understand that I can achieve what I want easily via method overriding. I'm just curious about what's happenning under the hood.

Thanks in advance.

like image 960
Boyang Avatar asked Feb 18 '23 02:02

Boyang


2 Answers

When you call, s1.toString(), it's finding toString() method defined only in Super class hence using that method as super class methods are available in the sub class. Your super class method toString() is using it's own class variable str (with value initialized in super class) as the return value from the method and hence the behavior i.e. output as I'm super!.

If you want to get the output as I'm sub.\n then you need to reuse the same variable as in the super class and assign the new string value i.e. I'm sub.\n to it. Best option is to use constructors as:

  public class Super {
     String str = "I'm super!\n";

     public Super(String stringValue){
         this.str = stringValue;
     }

     public String toString() {
        return str;
     }
  }

  public class Sub extends Super {
     public Sub(){
       super("I'm sub.\n");
     }
  }

  public class TestFH {
    public static void main(String[] args) {
       Sub s1 = new Sub();
       System.out.printf(s1.toString());
    }
  }
like image 78
Yogendra Singh Avatar answered Feb 26 '23 19:02

Yogendra Singh


You're hiding (shadowing) str in your child class. Since you have not overridden toString() in your child class, the call is being made in the parent class, and it sees the parent's str.

If you did this:

public class Sub extends Super {
    public Sub() {
        this.str = "I'm sub.\n";
    }
}

It would output what you're expecting.

like image 25
Brian Roach Avatar answered Feb 26 '23 21:02

Brian Roach