UNC COMP 301 - F26/Lec 4 - Inheritance and Polymorphism
Watch on YouTube →
Overview
Muhammad Sayeed Ghani develops Java inheritance and polymorphism through a university model with a Person superclass and Student and Professor subclasses, explaining constructor chaining, object memory, and compile-time versus runtime types. He also covers interface default and static methods, multiple interface inheritance, the three forms of polymorphism, `instanceof`, and safe versus unsafe upcasting and downcasting.
Key takeaways
- A Java subclass instance contains inherited superclass state as part of the same object; constructing a Professor invokes the Person constructor through `super`, but does not allocate a separate Person object.
- The declared reference type determines which members the compiler permits, while the runtime object's class determines the result of `instanceof` and whether a downcast succeeds.
- Java permits a class to extend only one class, but an interface can extend multiple interfaces; combining `Tossable` and `Trackable` into `Juggleable` creates a contract requiring both method sets.
- Overloading and generic type selection are resolved at compile time; subtype polymorphism relies on the runtime instance, such as a Person reference holding a Professor.
- Upcasting a subtype to its parent is safe and implicit, but downcasting requires the object to be an instance of the target subtype or a `ClassCastException` occurs.
Chapters
- The Triangle interface adds an abstraction alongside Point, with methods such as `getArea` and `getPerimeter`.
- Implementations such as `Triangle` use `implements`; methods meant only for internal use should be private.
- A good interface exposes the methods and fields clients need while keeping implementation details private.
- Cartesian and polar Point implementations share `equals` and `distance2`, which can become default methods when they rely only on interface methods such as `getX` and `getY`.
- A default method cannot depend on implementation-specific private methods unavailable through the interface contract.
- An interface static method is called through the interface name, as in `InterfaceName.method()`.
- Interfaces are useful when multiple classes need to share a contract and provide different implementations.
- If there is only one implementation and no meaningful shared abstraction, an interface may add unnecessary complexity.
- The lecture then introduces inheritance as the next major topic, using a university people-management example.
- Without inheritance, Student and Professor duplicate their shared `name` field and `getName` method.
- A `Person` superclass holds the common name field, constructor, and getter, while Student retains credits and Professor retains rank status.
- Java uses `extends` to declare a subclass, and the subclass constructor calls the parent constructor with `super(name)` as its first statement.
- Creating a Professor first enters the Professor constructor and then invokes the Person constructor through `super`.
- The debugger shows one Professor object, not a separate Person object; the Person constructor initializes the inherited portion of that same instance.
- The inherited `name` field is initially null and becomes `Emily` when the Person constructor assigns its argument.
- A Professor object's memory includes inherited Person state as well as Professor-specific state such as rank status.
- A set diagram places Professors and Students inside the broader set of Persons; a heap diagram instead shows the Person portion inside one Professor object.
- In `Professor kim = new Professor(...)`, the declared type and runtime object are both Professor, while `new` creates the object and returns its reference.
- In `Person kim = new Professor(...)`, the variable's compile-time type is Person while its runtime object is Professor.
- This relationship is subtype polymorphism: one reference can be viewed through a superclass type while referring to a subclass instance.
- Interfaces can extend other interfaces; for example, `CompressedMedia` can extend `Media` and add contract methods.
- Unlike Java classes, which can extend only one class, an interface can extend multiple interfaces.
- `Juggleable` can extend both `Tossable` and `Trackable`, combining methods for throwing an object and tracking its position, velocity, and acceleration.
- A class implementing `Juggleable` must implement the combined abstract-method contract.
- Subtype polymorphism comes from inheritance and interfaces, where a reference can represent an instance of a subtype.
- Ad hoc polymorphism is method overloading; methods share a name but differ in parameter count or parameter types.
- Parametric polymorphism is generics, such as using a type parameter `T` in a collection or method.
- Java cannot overload methods based only on return type; the parameter lists must distinguish the signatures.
- The compiler resolves overloaded calls from their argument count and types, and determines generic types such as `ArrayList<String>` at compile time.
- Subtype polymorphism depends on the runtime object: `new Professor(...)` creates the actual Professor instance at runtime even when stored in a Person variable.
- Inheritance should express an is-a relationship: a Student is a Person and a Professor is a Person, but not every Person is either subtype.
- The `instanceof` operator checks whether the runtime object on its left is an instance of the type on its right.
- For a reference to a plain Person object, `instanceof Person` is true while `instanceof Student` and `instanceof Professor` are false.
- A Student object satisfies both `instanceof Student` and `instanceof Person` because Student extends Person.
- A Professor object likewise satisfies `instanceof Professor` and `instanceof Person`, even when the reference is declared as Person.
- These checks follow the runtime object's inheritance chain, not just the reference variable's declared type.
- A Person reference to a Professor can be explicitly cast to Professor so code can access subclass-specific methods or fields such as rank status.
- The compiler sees the reference as Person before the cast, so it restricts direct access to members declared only in Professor.
- A downcast is valid only when the runtime object really is an instance of the requested subclass.
- Casting a Person reference that actually points to a Student into Professor can compile when the types are related, but it fails at runtime with a `ClassCastException`.
- Student and Professor are sibling subclasses of Person, so a Student object cannot be converted into a Professor object by casting.
- Casting a reference to a newly created plain Person directly to Professor is rejected at compile time because the classes have no applicable subtype relationship.
- Upcasting a Professor reference to Person is always safe because every Professor is a Person; Java performs the conversion implicitly.
- The closing examples show a Student-to-Person cast and a Person reference to a Professor as valid, but a Professor-to-Student cast as an invalid sibling downcast.
- A downcast may compile yet fail at runtime, while an upcast needs no explicit cast.
Summary, takeaways, and chapters were generated by AI from the video's transcript and may contain errors. The video belongs to its creator, Muhammad Sayeed Ghani.