View on GitHub

Notes

reference notes

Inheritance and Polymorphism

Introduction to Inheritance

In Java, inheritance is a mechanism wherein a class (subclass) acquires all the properties and behaviors of a parent (super) class. This allows the creation of new classes built upon existing ones, enabling the reuse of methods and fields from parent classes. Additionally, new methods and fields can be added to the current classes.

Simple Example

To illustrate inheritance, consider modeling different types of pets such as dogs and cats. The Pet class serves as the superclass, while Dog and Cat classes are subclasses inheriting from Pet. The example demonstrates how subclasses can override inherited methods or introduce new ones.

Pet
 |
 |-- Dog
 |
 |-- Cat

The Pet Class

class Pet {
    private String name;
    
    public String getName() {
        return name;
    }

    public void setName(String petName) {
        name = petName;
    }

    public String speak() {
        return "I’m your cuddly little pet.";
    }
}

Subclasses of The Pet Class

class Cat extends Pet {
    public String speak() {
        return "Don’t give me orders.\nI speak only when I want to.";
    }
}

class Dog extends Pet {
    public String fetch() {
        return "Yes, master. Fetch I will.";
    }
}

Sample Usage of the Subclasses

Dog myDog = new Dog();
System.out.println(myDog.speak());
System.out.println(myDog.fetch());

Cat myCat = new Cat();
System.out.println(myCat.speak()); // This will cause an ERROR as 'fetch' is not defined in the Cat class

Defining Classes with Inheritance

To define a subclass from a superclass, use the extends clause. The syntax is:

class Subclass extends Superclass {
    // ...
}

Defining Classes with Inheritance

Classes with an “is-a” relationship can be modeled using inheritance. For example:

class Cat extends Mammal { }

class FulltimeEmployee extends Employee { }

Simple rules:

Modeling Two Types of Students

To model undergraduate and graduate students, two approaches can be considered: unrelated classes or an inheritance hierarchy.

Classes for the Class Roster

For the Class Roster example, three classes are designed:

The Student class incorporates behavior and data common to both UndergraduateStudent and GraduateStudent objects, while the latter two contain specific behaviors and data.

Inheritance Hierarchy

A visual representation of the hierarchy can help understand the relationships between classes.

The Protected Modifier

The protected modifier allows a data member or method to be accessed within its own class, any class derived from it, and any classes in the same package. This is contrasted with public (accessible to any class) and private (accessible only within its own class).

Visibility Modifier

Visibility modifiers include public, protected, default/package (omitted first modifier), and private. Visibility decreases from own class to any classes, own class and subclasses, and own class and any classes in the same package.

Visibility:      public      protected      default      private
                 ------------------------------------------------
Own class             Y              Y            Y             Y
                 ------------------------------------------------
Any classes          Y              Y            Y             N
                 ------------------------------------------------
Own class and
Subclasses           Y              Y            N             N
                 ------------------------------------------------
Any classes in
the same package    Y              Y            N             N
                 ------------------------------------------------
Own class and
Any classes
in the same
package             Y              N            N             N
                 ------------------------------------------------

This organization emphasizes the principles of inheritance, showcasing its application in modeling different types of objects and establishing relationships between classes.

Polymorphism

Introduction to Polymorphism

Polymorphism allows a single variable to refer to objects from different subclasses within the same inheritance hierarchy. For instance, if Cat and Dog are subclasses of Pet, statements like Pet myPet; myPet = new Dog(); demonstrate the flexibility of polymorphism.

Creating the Roster Array

To manage a class roster, an array can be utilized, accommodating objects from the Student, UndergraduateStudent, and GraduateStudent classes.

Student roster = new Student[40];
roster[0] = new GraduateStudent();
roster[1] = new UndergraduateStudent();
roster[2] = new UndergraduateStudent();
// ...

Sample Polymorphic Message

To compute the course grade using the roster array, a loop can be employed to invoke the computeCourseGrade method for each student. This demonstrates polymorphic behavior based on the actual type of the object being referred to.

for (int i = 0; i < numberOfStudents; i++) {
    roster[i].computeCourseGrade();
}

Methods Overriding

Method overriding allows a subclass to provide a specific implementation of a method declared in the superclass. Rules include maintaining the same method name and parameters as in the superclass.

Example:

class Vehicle {
    void run() {
        System.out.println("Vehicle is running");
    }
}

class Bike extends Vehicle {
    void run() {
        System.out.println("Bike is running safely");
    }

    public static void main(String args[]) {
        Bike obj = new Bike();
        obj.run();
    }
}

Output:

Bike is running safely

The instanceof Operator

The instanceof operator helps determine the class of an object. For example, to count the number of undergraduate students in the roster:

int undergradCount = 0;
for (int i = 0; i < numberOfStudents; i++) {
    if (roster[i] instanceof UndergraduateStudent) {
        undergradCount++;
    }
}

Inheritance and Member Accessibility

Visual representation of inheritance illustrates data member accessibility. Everything except private members of the superclass is visible from a method of the subclass.

Class Hierarchy

Class Hierarchy
    |
Superclass
    |
Subclass
    |
Instances

Accessibility from the Client Method

The accessibility of members between packages is demonstrated, emphasizing the visibility of protected, default, and public members.

package one;
package two;
// Refer to Client.java

Accessibility of Super from Sub

In a subclass, everything except private members of the superclass is visible from a method of the subclass. This facilitates the utilization of inherited components.

Inheritance and Constructors

Introduction to Constructors in Inheritance

When an object of a subclass is created, the constructor for both the superclass and the subclass is executed. The superclass constructor must execute first, followed by the subclass constructor.

class ClassA {
    public ClassA() {
        System.out.println("In superclass constructor");
    }
}

class ClassB extends ClassA {
    public ClassB() {
        System.out.println("In subclass constructor");
    }
}

class Demo {
    public static void main(String[] args) {
        ClassB child = new ClassB();
    }
}

Output:

In superclass constructor
In subclass constructor

Inheritance and Constructors

Example:

public class Vehicle {
    private int numWheels;
    private double milesPerGallon;

    public Vehicle() {
        this(0, 0.0);
        System.out.println("Default object, values not set.");
    }

    public Vehicle(int numWheels, double milesPerGallon) {
        this.numWheels = numWheels;
        this.milesPerGallon = milesPerGallon;
    }

    public String toString() {
        return "Number of wheels " + numWheels + ". Average number of miles per gallon " + milesPerGallon + ".\n";
    }
}

public class Car extends Vehicle {
    public Car() {
        super();
    }

    public Car(double milesPerGallon) {
        super(4, milesPerGallon);
    }
}

public class Motorcycle extends Vehicle {
    public Motorcycle(double milesPerGallon) {
        super(2, milesPerGallon);
    }
}

public class VehicleProject {
    public static void main(String[] args) {
        Car car1 = new Car();
        Car car2 = new Car(10.0);
        Motorcycle motor = new Motorcycle(25.0);

        System.out.println(car1.toString());
        System.out.println(car2.toString());
        System.out.println(motor.toString());
    }
}

Output:

Default object, values not set.
Number of wheels 0. Average number of miles per gallon 0.0.
Number of wheels 4. Average number of miles per gallon 10.0.
Number of wheels 2. Average number of miles per gallon 25.0.

Keyword super

public class Superclass {
    public void printMethod() {
        System.out.println("Printed in Superclass.");
    }
}

public class Subclass extends Superclass {
    // overrides printMethod in Superclass
    public void printMethod() {
        super.printMethod();
        System.out.println("Printed in Subclass.");
    }

    public static void main(String[] args) {
        Subclass s = new Subclass();
        s.printMethod();
    }
}

Output:

Printed in Superclass.
Printed in Subclass.

Abstract Superclasses and Abstract Methods

Example:

abstract class Student {
    // ...
    abstract public void computeCourseGrade();
}

Definition: Abstract Class

Definition: Abstract Method

Example:

abstract public void computeCourseGrade();

Case 1: Student Must Be Undergraduate or Graduate

Case 2: Student Does Not Have to Be Undergraduate or Graduate

Interface

Example:

public interface OperateCar {
    // constant declarations, if any
    // method signatures
    int turn(Direction direction, double radius, double startSpeed, double endSpeed);
    int changeLanes(Direction direction, double startSpeed, double endSpeed);
    int signalTurn(Direction direction, boolean signalOn);
    int getRadarFront(double distanceToCar, double speedOfCar);
    int getRadarRear(double distanceToCar, double speedOfCar);
    // more method signatures
}

Inheritance vs. Interface

When to Use Inheritance:

When to Use Interface:

Abstract Class vs. Interface

Reference: Oracle Java Tutorial