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
    }
    
}

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. Test your solution with DiceTest.java before submitting to Gradescope.

  • Your super class should be called Dice – constructor call: 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): random.nextInt(sides) + 1;
  • Create a subclass called BiasedDice (use extends keyword) with getters for favored side and bias (getFavored() and getBias())
    • roll() method 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 each of landing on 1, 2, 4, 5, and 6. (if (random.nextDouble() < bias) { return favored; })
    • public void setFavored(int favored, double bias) – favored must be in [1, number of sides], bias must be in [0.0, 1.0]

Super class solution

import java.util.Random;

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

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

    public int getSides() {
        return sides;
    }

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

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 Package Subclass World
public Yes Yes Yes Yes
protected Yes Yes Yes No
default Yes Yes No No
private Yes No No No

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) {
        if (favored < 1 || favored > getSides() || bias < 0.0 || bias > 1.0) {
            return;
        }
        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;
    }
}

Quiz 06

You have 10 minutes to complete the quiz.

Choose on one choice for each question. Multiple marks on different choices will be graded as zero.