(OOP4) Inheritance

(OOP4) Inheritance

Once you create a superclass that defines the attributes common to a set of objects, it can be used to create any number of more specific subclasses - each precisely tailored to its own classification.

Dynamic Method Dispatch

In a class hierarchy, when a method in a subclass has the same name and type signature as a method in the superclass, then the method is said to override the superclass method. When this method is called, it will always refer to the version defined in the subclass. This is also known as method overriding, and is a form of run-time polymorphism.
class A { int i, j; A(int a, int b) { i = a; j = b; } void show() { System.out.println("i and j: " + i + " " + j); } } class B extends A { int k; B(int a, int b, int c) { super(a, b); k = c; } void show() { System.out.println("k: " + k); } } public class Override { public static void main(String[] args) { B subObj = new B(1, 2, 3); subObj.show(); // prints 'k: 3' and nothing else. } }
class B extends A { // ... void show() { super.show(); // calls A's show(). System.out.println("k: " + k); } }

Using ‘super’

A subclass can call a constructor defined in its superclass by using super(arg-list).
class BoxWeight extends Box { double weight; // Box has a constructor to specify w/h/d. BoxWeight(double w, double h, double d, double m) { super(w, h, d); weight = m; } }
You can also access members/methods of the superclass using super.member. (This can set a different value of the same variable in the superclass and the subclass.)

Superclass Referencing Subclass

public class RefDemo { public static void main(String[] args) { BoxWeight weightbox = new BoxWeight(3, 5, 7, 8.37); Box plainbox = new Box(); System.out.println("Volume of weightbox: " + weightbox.volume()); System.out.println("Weight of weighbox: " + weightbox.weight); System.out.println(); // assign BoxWeight ref. to Box ref. plainbox = weightbox; System.out.println("Volume of plainbox: " + plainbox.volume()); System.out.println("Weight of weighbox: " + plainbox.weight); // Error: 'weight' not defined for plainbox! } }

Constructor Execution

class A { A() { System.out.println("Inside A's constructor."); } } class B extends A { B() { System.out.println("Inside B's constructor."); } } class C extends B { C() { System.out.println("Inside C's constructor."); } } public class CallingConstructors { public static void main(String[] args) { C c = new C(); } }
PS F:\oopsies> Inside A's constructor. Inside B's constructor. Inside C's constructor.

Abstract Classes

abstract class Vehicle { // Only abstract classes have abstract methods. abstract void numberOfGears(); // Abstract methods have no content. The content // is defined in the inheriting classes. } class Car extends Vehicle { // Since we have inherited Vehicle, we MUST // create a numberOfGears() method. void numberOfGears() { System.out.println("This vehicle has 5 gears."); } } class Bike extends Vehicle { void numberOfGears() { System.out.println("This vehicle has 4 gears."); } } public class AbstractStuff { public static void main(String[] args) { // We can now access this, only using // the subclasses that inherit from Vehicle. Car marutiCar = new Car(); marutiCar.numberOfGears(); Car toyotaCar = new Car(); toyotaCar.numberOfGears(); Bike kawasakiBike = new Bike(); kawasakiBike.numberOfGears(); Bike avengerBike = new Bike(); avengerBike.numberOfGears(); } }

Using ‘final’ in Inheritance

Overriding Prevention

class A { final void meth() { System.out.println("This is a final method."); } } class B extends A { void meth() { System.out.println("Error: Cannot override!"); } }
Java normally resolves calls to methods dynamically at runtime, called late binding. But since ‘final’ methods are “known” to not be subclassed/overridden, the call is resolved at compile time as early binding.

Inheritance Prevention

final class A { // ... } class B extends A { // Error: Can't subclass a 'final' class! }
It is illegal to declare a class as both abstract and final, as an abstract class is incomplete by itself and relies upon its subclasses to provide complete implementations.

The Object Class

The Object class in Java is a superclass to all other classes. Hence, a reference variable of type ‘Object’ can refer to an object of any other class, or to any other array. It has the following pre-defined methods, available in every object.
notion image
The methods getClass(), notify(), notifyAll(), and wait() are ‘final’, and all others can be overridden. The toString() method is automatically called when the object is referenced inside println().