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
getMake
setMake
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();
}
}
}