Field and Method Hiding in Java
Field Hiding
Field hiding is when you have the same variable name used in a superclass and a subclass. The type doesn't have to match only the name. You could have a protected or public variable in a superclass and the same variable name that is protected or public in a subclass.
public class SuperClass {
protected int value = 0;
}
public class SubClass extends SuperClass {
protected int value = 1;
public void print() {
// Prints: 1
System.out.print(value);
}
}
In SubClass, the variable value in SuperClass is hidden. When you are in SubClass, you would use the variable value in the SubClass, not what is in the SuperClass. Similar to using this, you could use super so the value variable in SuperClass isn't hidden.
public class SubClass extends SuperClass {
protected int value = 1;
public void print() {
// Prints: 0
System.out.print(super.value);
}
}
This fixes the hiding issue, but really the underlining issue is the lack of encapsulation. You should never have fields in an inheritance structure that are marked as anything but private. Field hiding is a great example as to why fields should always be private. To properly solve this issue, you'd want to mark value as private and provide an assessor method in SuperClass for value().
public class SuperClass {
private int value = 0;
public int value() {
return value;
}
}
Now in SubClass, you can either use value() or override it depending on what the intent is.
Although field hiding is legal, it should be avoided and not done intentionally. This creates confusing code and increases the chance of bugs. With proper encapsulation, field hiding should never be an issue.
Method Hiding
Method hiding occurs with static methods. Method hiding is when you have a static method with the same signature in a superclass and in a subclass.
public class SuperClass {
public static void greet() {
System.out.println("SuperClass - Hello");
}
}
public class SubClass extends SuperClass {
public static void greet() {
System.out.println("SubClass - Hello");
}
}
Depending on how greet() is called, it will result in different outputs.
// Prints: SuperClass - Hello
System.out.println(SuperClass.greet());
// Prints: SubClass - Hello
System.out.println(SubClass.greet());
This can also occur when you have a nested class that has the same static method signature in the outer class that it is defined in.
public class OuterClass {
public static void greet() {
System.out.println("OuterClass - Hello");
}
public static class NestedClass {
public static void greet() {
System.out.println("NestedClass - Hello");
}
}
}
Hiding can be solved by just calling the correct class for the method you want to invoke, so what is the problem? What if you had code that started out like the following:
public class SuperClass {
public static void greet() {
System.out.println("SuperClass - Hello");
}
}
public class SubClass extends SuperClass {
}
This allows you to call greet() one of two ways.
SuperClass.greet();
SubClass.greet();
Down the road, the same method signature is introduced in SubClass with different behavior. This potentially changes the behavior in every one of these methods. You may not know what will call SuperClass.greet() and what will call SubClass.greet() depending on how the code is written.
With static method signatures, keep them unique in the inheritance structure to avoid method hiding. Method hiding is a recipe to introduce unintended behavior and bugs.
Conclusion
Field and method hiding is something that should never intentionally be done. It causes confusing code and can introduce bugs. Always properly encapsulate fields, and try to keep static methods at a minimum. Always uniquely name static methods in an inheritance structure when you can.