Java - Inheritance & Polymorphism
Inheritance & Polymorphism
extends and super
class Animal { void speak() { System.out.println("..."); } }
class Dog extends Animal {
  @Override void speak() { System.out.println("Woof"); }
}
Animal a = new Dog();
a.speak(); // Woof (dynamic dispatch)
Method Overriding and final
Use @Override to catch mistakes. final prevents further overriding, final class prevents inheritance.
Constructors and super()
class Base { Base(int n) {} }
class Sub extends Base { Sub() { super(42); } }
Composition over Inheritance
Prefer composition when reuse does not model an "is-a" relationship.
Liskov Substitution Principle (LSP)
Subtypes must honor supertype contracts. Avoid strengthening preconditions or weakening postconditions.
Avoid deep inheritance hierarchies. Favor small, cohesive types and interfaces.
  Try it
- Create a small hierarchy (Animal→Dog/Cat) and override a method; observe dynamic dispatch.
- Mark a class finaland attempt to extend it (should fail).