Inheritance

CSCI 1913 – Introduction to Algorithms, Data Structures, and Program Development
Adriana Picoral

Class relations

  • uses-a – when a class uses another class
  • has-a – when a class has an instance of another class
  • has-many – many instances of other classes
  • is-a – a subclass extends a super class

An is-a relationship exists when one class can be seen as a more specific version of another class

is-a relationship

An is-a relationship exists when one class can be seen as a more specific version of another class

Most programming languages support is-a relationships using inheritance

Inheritance

Attributes and methods can be inherited from one class to another

  • superclass (parent) - the class being inherited from
  • subclass (child) - the class that inherits from another class

Use the extends keyword

Superclass

Create a class called Person with the following instance variables:

  • First Name
  • Family Name
  • Birthdate

What public and private methods?

Make sure you do validation for setter methods.

Superclass solution

import java.time.LocalDate;

public class Person {
    
    private String firstName;
    private String familyName;
    private int birthYear;
    private int birthMonth;
    private int birthDay;

    public Person(String first, String family) {
        firstName = first;
        familyName = family;
    }
    
    public void setBirthDate(int year, int month, int day) {
        LocalDate today = LocalDate.now(); 
        if (year > 1900 && year <= today.getYear()) birthYear = year;
        if (month > 0 && month <= 12) birthMonth = month;
        if (day > 0 && day <= 31) birthDay = day;
    }
    
    public String getBirthDate() {
        String month;
        if (birthMonth < 10) month = "0" + birthMonth;
        else month = "" + birthMonth;
        return birthYear + "/" + month + "/" + birthDay;
    }
    
    public String getFirstName() {
        return firstName;
    }
    
    public String getFamilyName() {
        return familyName;
    }
    
    public String toString() {
        String message = firstName + " " + familyName;
        message += " born on " + getBirthDate();
        return message
    }
    
}

Quiz 06

You have 10 minutes to complete the quiz

Subclass

Create a class called Student that extends the Person class. Add the following instance variables:

  • Admissions Year
  • Graduation Year
  • Major
  • Email address (or only netID)

What public and private methods?

Write a constructor method, invoke base-class constructor using super keyword

Constructor inheritance

The constructor rule: Before any method in a class is run, one of the constructors of that class will run

  • Constructor sets-up object before anything else
  • You can rely on this simple rule

Constructor inheritance

How does this interact with inheritance?

  • We might call an inherited method
  • Therefore, we must arrange a constructor call first!

Child class constructor obligation

Child class constructors must call a parent class constructor.

  • Implicitly the default constructor is called
  • Explicitly you have to call a specific constructor

Constructor call syntax:

public ChildClass(<params>) {
   super(...)
}
  • This has to be first line of code (which sucks sometimes)
  • parameters to super(...) match one of the parent class constructor

Subclass solution

import java.time.LocalDate;

public class Student extends Person {
    private int admissionYear;
    
    public Student(String first, String family,
                   int admissionYear) {
        // invoke base-class constructor
        super(first, family);
        LocalDate today = LocalDate.now(); 
        if (admissionYear > 1900 && admissionYear <= today.getYear()) 
            this.admissionYear = admissionYear;
    }
    
    public int getAdmission() {
        return admissionYear;
    }
    
    public void print() {
        String message = super.toString();
        message += "Admitted in " + admissionYear;
        return message
    }

}

Practice

Implement two Java classes that simulate rolling dice — a fair die and a biased die — while practicing inheritance.

What instance variables should Dice.java have?

Methods:

  • Constructor (with number of sides as a parameter) – public Dice(int sides)
  • getter for number of sides – public int getSides()
  • public int roll() – returns an integer between 1 and number of sides (needs random module)
import java.util.Random;
Random random = new Random();
random.nextInt(sides) + 1;

Super class solution

import java.util.Random;

public class Dice {
    private int sides = 6;
    private Random random = new Random();

    public Dice(int sides) {
        this.sides = sides;
    }

    public int getSides() {
        return sides;
    }

    public int roll() {
        return random.nextInt(sides) + 1;
    }
}

Part 2: The BiasedDice Class

In a separate file (BiasedDice.java), create a subclass of Dice (use extends keyword) that favors one side with a specified probability. For example, if the favored sides equals 3 and bias equals 0.5, then a 6-sided die has a 50% chance of landing on 3 and a 10% chance of landing on 1, 2, 4, 5, and 6.

Part 2: The BiasedDice Class

  • Override roll():
    • With probability bias, return the favored side.
    • Otherwise, choose uniformly among the remaining sides.
    • e.g., if favored equals 3 and bias equals 0.5, then a 6-sided die has a 50% chance of landing on 3 and a 10% chance of landing on 1, 2, 4, 5, and 6.

protected keyword

The public access modifier specifies the variable can be accessed by any external class

The private access modifier specifies the variable can only be accessed in its own class

The protected access modifier specifies that the variable can only be accessed by a subclass of its class

access modifiers

Class Subclass World
public Yes Yes Yes
protected Yes Yes No
private Yes No No

Part 2: The BiasedDice Class

You can use the random object from the super class (change access modifier to protected) and then use the .nextDouble() method to get a double between 0 and 1. If this double is within the bias treshold return favored, otherwise return one of the other sides (randomly).

if (random.nextDouble() < bias) { return favored; }

Part 2: The BiasedDice Class

In a separate file (BiasedDice.java), create a subclass of Dice (use extends keyword) that favors one side with a specified probability. Methods:

  • Constructor: public BiasedDice(int sides)
  • public void setFavored(int favored, double bias)
    • favored must be in [1, number of sides]
    • bias must be in [0.0, 1.0]
  • getters for favored side and bias (getFavored() and getBias())

BiasedDice Class – solution

public class BiasedDice extends Dice {
    private int favored = 1;
    private double bias = 0.1;

    public BiasedDice(int sides) {
        super(sides);
    }

    public void setFavored(int favored, double bias) {
        this.favored = favored;
        this.bias = bias;
    }

    public int getFavored() {
        return favored;
    }

    public double getBias() {
        return bias;
    }

    public int roll() {
        if (random.nextDouble() < bias) {
            return favored;
        }

        int die = random.nextInt(getSides()) + 1;
        while (die == favored) {
            die = random.nextInt(getSides()) + 1;
        }
        return die;
    }
}