Memra

Overriding vs hiding: @Override, covariant returns & access rules

Instance methods are overridden at runtime; static methods and fields are hidden at compile time.

The critical distinction: override vs hide

Instance method overriding — when a subclass defines an instance method with the same signature as the parent, calls on a subclass object use the subclass version, regardless of the reference type. This is runtime dispatch.

Static method hiding — when a subclass defines a static method with the same signature, the method used is determined by the reference type at compile time, not the object. This is not polymorphism.

class Parent {
    String describe() { return "Parent instance"; }
    static String kind()  { return "Parent static"; }
}

class Child extends Parent {
    @Override
    String describe() { return "Child instance"; }  // overrides
    static String kind() { return "Child static"; } // hides
}

Parent p = new Child();
System.out.println(p.describe()); // Child instance  — runtime dispatch
System.out.println(p.kind());    // Parent static   — compile-time reference type

Rules for a valid override:

- Same method name and parameter types. - Return type must be the same or a covariant subtype (e.g., overriding Animal get() with Dog get() is valid). - Access modifier may be the same or wider (e.g., package-private → public is fine; public → private is a compile error). - Checked exceptions may be removed or replaced with a narrower checked exception — never a broader one.

@Override annotation instructs the compiler to verify these rules. Always use it; it turns a silent "I accidentally created a new method" bug into a compile error.

NORMAL ~/memra/learn/java-from-zero/overriding-vs-hiding utf-8 LF