Skip to content

Knowledge Supplement before Lecture 7

Inheritance

Sometimes one class A want to attribute and methods in another class B, then A can inherit class B

For example, we have a class Vehicle.java​ and a class Car.java​, then we know Car is a Vehicle, thus Car should own the methods in Vehicle.java​. In this situation, Car.java​ inherit Vehicle.java

The reason is if we have Bicycle.java​,.... we don't need to write the common methods and fields many times

Vehicle.java

public class Vehicle {
    double speed;
    void go() {
        System.out.println("This vehicle is moving");
    }

    void stop() {
        System.out.println("This vehicle is stopped");
    }

}

In order to use inheritance, we need to add extends <inherited class name>

For example, public class Car​ should become public class Car extends Vehicle

In this situation, Car class becomes subclass of Vehicle class, and Vehicle class is superclass

Car.java

public class Car extends Vehicle{

}

Main.java

public class Main {
    public static void main(String[] args) {
        Car car = new Car();
        car.go();
        System.out.println(car.speed);
    }
}
// The terminal will print This Vehicle is moving
//0.0

Another advantage is that subclass could has unique additional attribute and methods

For example, Car and Bicycle are not same, they should have distinct methods and attributes

Car.java

public class Car extends Vehicle{
    int wheels = 4;
    int doors = 4;
}

Bicycle.java

public class Bicycle extends Vehicle{
    int wheels = 2;
    int pedals = 2;
}

Main.java

public class Main {
    public static void main(String[] args) {
        Car car = new Car();
        Bicycle bike = new Bicycle();
        System.out.println(car.doors);
        System.out.println(bike.pedals);
    }
}
// The terminal will print
//4
//2

Method overriding

Declaring a method in sub class, which is already present in parent class. done so that a child class can give its own implementation

Let's see an example

Main.java

public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.speak();
    }
}

Animal.java

public class Animal {
    void speak() {
        System.out.println("The animal is speaking");;
    }
}

Dog.java

public class Dog extends Animal {

}

Now we are going to give the own implement of speak method using method overwriting

Dog.java

public class Dog extends Animal {

    @Override //This is not mandatory, but a convention
    void speak() {
        System.out.println("The dog goes bark");;
    }
}

Main.java

public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.speak();
        Animal animal = new Animal();
        animal.speak();
    }
}
//The terminal:
//The dog goes barking
//The animal is speaking

Super keyword

This keyword refers to the superclass of an object, which is very similar to this keyword

Initially, we can do this

Main.java

public class Main {
    public static void main(String[] args) {
        Hero hero1 = new Hero("Batman", 42, "$$$");
    }
}

Person.java

public class Person {
    String name;
    int age;

    Person(){

    }
}

Hero.java

public class Hero extends Person {
    String power;

    Hero(String name, int age, String power){
        this.name = name;
        this.age = age;
        this.power = power;
    }
}

However, this is not a good way since we've already extends Person, then we need to utilize class Person

Let's do this

Person.java

public class Person {
    String name;
    int age;

    Person(String name, int age){
        this.name = name;
        this.age = age;
    }
}

Hero.java

public class Hero extends Person {
    String power;

    Hero(String name, int age, String power){
        super(name, age);//called constructor in Person
        this.power = power;
    }
}

Main.java

public class Main {
    public static void main(String[] args) {
        Hero hero1 = new Hero("Batman", 42, "$$$");
        System.out.println(hero1.name);
        System.out.println(hero1.age);
        System.out.println(hero1.power);

Then to make print more efficiently, we can modify class Person

Person.java

public class Person {
    String name;
    int age;

    Person(String name, int age){
        this.name = name;
        this.age = age;
    }

    public String toString() {
        return this.name + "\n" + this.age + "\n";
    }
}

Hero.java

public class Hero extends Person {
    String power;

    Hero(String name, int age, String power){
        super(name, age);//called constructor in Person
        this.power = power;
    }

    public String toString() {
        return super.toString() + this.power;
    }
}

Main.java

public class Main {
    public static void main(String[] args) {
        Hero hero1 = new Hero("Batman", 42, "$$$");
        Hero hero2 = new Hero("Superman", 43, "everything");
        System.out.println(hero2.toString());
}

Abstraction

Abstract classes cannot be instantiated, but they can have a subclass abstract methods are declared without an implementation

Vehicle.java

public class Vehicle {


}

Car.java

public class Car extends Vehicle{

}

Main.java

public class Main {
    public static void main(String[] args) {
        Vehicle vehicle = new Vehicle();
        Car car = new Car();

    }
}

Note that Vehicle vehicle = new Vehicle();​ this is nonsense in most situations because it's too general and necessary

Thus we want to prevent creating this object, then we can change Vehicle.java to a abstract class

Vehicle.java

public abstract class Vehicle {


}

Then we cannot creating Vehicle object, we need to provide certain type: Car, Bicycle,...


Let's implement this class with abstract method

But since the definition, we cannot add any implementation(body), just the signature of method

But we can also create a method without abstract keyword with specific implementation

Vehicle.java

public abstract class Vehicle {
    abstract void go();
}

If we do this, we must implement this method in subclass

Car.java

public class Car extends Vehicle{
    @override
    void go() {
        System.out.println("The driver is driving a car");
    }
}

Main.java

public class Main {
    public static void main(String[] args) {
        Car car = new Car();
        car.go();
    }
}
//The terminal: 
//The driver is driving a car

Encapsulation

attributes of a class will be hidden or private, Can be accessed only through methods (getters & setters) You should make attributes private if you don't have a reason to make them public/protected

Visibility/Class From class A (package pA) From class A2 (package pA) From class B2 (package pB, subclass of A) From class B1 (package pB)
private ACCESSIBLE INACCESSIBLE INACCESSIBLE INACCESSIBLE
package ACCESSIBLE ACCESSIBLE INACCESSIBLE INACCESSIBLE
protected ACCESSIBLE ACCESSIBLE ACCESSIBLE INACCESSIBLE
public ACCESSIBLE ACCESSIBLE ACCESSIBLE ACCESSIBLE

Car.java

public class Car{
    private String make;
    private String model;
    private int year;
    Car(String make, String model, int year){
        this.make = make;
        this.model = model;
        this.year = year;
    }
}

If we want to access fields of Car in other class, we cannot directly access it. We should use getters and setters

getMakesetMake

Copy objects

If we create two instances A and B and we do A = B​. Actually the reference of B will be copied to A

Better way is to set the fields of B to A by setters and getters

Interface

a template that can be applied to a class. similar to inheritance, but specifies what a class has/must do. classes can apply more than one interface, inheritance is limited to 1 super class

Main.java

public class Main {

    public static void main(String[] args) {

    }

}

Rabbit.java

public class Rabbit {

}

Hawk.java

public class Hawk {

}

The we define some interface

Prey.java

public interface Prey {
    void flee();
}

Predator.java

public interface Predator {
    void hunt();
}

In this interface, we can declare variables and methods without body

Then we need to implement that method in the Rabbit,....

Rabbit.java

public class Rabbit implements Prey {
    @Override
    public void flee() {
        System.out.println("The rabbit is fleeing");
    }
}

Main.java

public class Main {

    public static void main(String[] args) {
        Rabbit rabbit = new Rabbit();
        rabbit.flee();
    }
}
//Terminal
//The rabbit is fleeing

Continue

Hawk.java

public class Hawk implements Predator {
    @Override
    public void hunt() {
        System.out.println("The hawk is hunting");
    }
}

Main.java

public class Main {

    public static void main(String[] args) {
        Hawk hawk = new Hawk();
        hawk.hunt();
    }
}
//Terminal
//The rabbit is fleeing

Also more than one implements are allowed

Fish.java

public class Fish implements Prey, Predator{
    @Override
    public void hunt() {
        System.out.println("The finsh is hunting smaller fish");
    }

    @Override
    public void flee() {
        System.out.println("This fish is fleeing from a larger fish");
    }   
}

Main.java

public class Main {

    public static void main(String[] args) {
        Fish fish = new Fish();
        fish.hunt();
        fish.flee();
    }
}
//Terminal
//The finsh is hunting smaller fish
//This fish is fleeing from a larger fish

Polymorphism

greek word for poly-"many", morph-"form"

The ability of an object to identify as more than one type

Vehicle.java

public class Vehicle {


}

Car.java

public class Car extends Vehicle{

}

Bicycle.java

public class Bicycle extends Vehicle{

}

Boat.java

public class Boat extends Vehicle{

}

Main.java

public class Main {
    public static void main(String[] args) {
        Car car = new Car();
        Bicycle bicycle = new Bicycle();
        Boat boat = new Boat();
        Vehicle[] racers = {car, bicycle, boat};


    }
}

If we want to create Car[] racers = {car, bicycle, boat};​ there will be issue

But we know car, bicycle, boat are all vehicles

Then we can Vehicle[] racers = {car, bicycle, boat};​. This is a polymorphsim


Car.java

public class Car extends Vehicle{
    public void go() {
        System.out.println("The car begins moving");
    }
}

Bicycle.java

public class Bicycle extends Vehicle{
    public void go() {
        System.out.println("The bicycle begins moving");
    }
}

Boat.java

public class Boat extends Vehicle{
    public void go() {
        System.out.println("The boat begins moving");
    }
}

Then we can call them

Main.java

public class Main {
    public static void main(String[] args) {
        Car car = new Car();
        Bicycle bicycle = new Bicycle();
        Boat boat = new Boat();
        Vehicle[] racers = {car, bicycle, boat};

        //method 1, not good
        //car.go();
        //bicycle.go();
        //boat.go();

        //method 2, good
        for(Vehicle x : racers) {
            x.go();
        }
    }
}

But in method 2, the method go() is not defined for type Vehicle

Thus we need to add this in class Vehicle

Vehicle.java

public class Vehicle {
    public void go() {
    }
}

By the way, we should add @Override​ before each Vehicle

Then the program works

Also, car, bicycle, boat are all child class of Object, thus it's valid of Object[] racers = {car, bicycle, boat};

Dynamic polymorphsim

polymorphism = many shapes/forms

dynamic = after compilation (during runtime)

ex. A corvette is a: corvette, and a car, and a vehicle, and an object

Main.java

public class Main {
    public static void main(String[] args) {
        //Animal animal = new Dog(); //Cat(),... ask user during the run time
                                  //we cannot assume that

    }
}

Animal.java

public class Animal{
    public void speak() {
        System.out.println("animal goes brrrr");
    }
}

Dog.java

public class Dog extends Animal{
    @Override
    public void speak() {
        System.out.println("dog goes bark");
    }   
}

Cat.java

public class Cat extends Animal{
    @Override
    public void speak() {
        System.out.println("cat goes mow");
    }   
}

Main.java

import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        Animal animal;

        System.out.println("What animal do you want");
        System.out.println("(1=dog) or (2=cat):");

        int choice = scanner.nextInt();
        if(choice == 1) {
            animal = new Dog();
            animal.speak();
        }
        else if(choice == 2) {
                animal = new Cat();
                animal.speak()
        }
        else {
            animal = new Animal();
            System.out.println("That choice was invalid");
            animal.speak();
        }
    }
}