You are on page 1of 72

Part 1:

Java as an Object-oriented
Programming Language

04. Inheritance
Let’s practice writing some classes

 Write an Employee class with methods that return


values for the following properties of employees at a
particular company:

 Work week: 40 hours


 Annual salary: $40,000
 Paid time off: 2 weeks
 Leave of absence form: Yellow form

2
Employee class
// A class to represent employees
public class Employee {
public int getHours() {
return 40; // works 40 hours / week
}

public double getSalary() {


return 40000.0; // $40,000.00 / year
}

public int getVacationDays() {


return 10; // 2 weeks' paid vacation
}

public String getVacationForm() {


return "yellow"; // use the yellow form
}
}
3
Shape classes

 Write a class called Rectangle with a width, a length, and


a method for calculating the area. Include a constructor.

 Write a Square class with a width, a method for


calculating the area, and a constructor.

 Write a Triangle class with lengths for each side. Include


a constructor, and a method for calculating the angle
between two sides.
 Write an EquilateralTriangle class …
Inheritance

5
Writing more classes

 Write a Secretary class with methods that return


values for the following properties of secretaries at a
particular company:

 Work week: 40 hours


 Annual salary: $40,000
 Paid time off: 2 weeks
 Leave of absence form: Yellow form

 Add a method takeDictation that takes a string


as a parameter and prints out the string prefixed by
"Taking dictation of text: ".

6
Secretary class
// A class to represent secretaries
public class Secretary {
public int getHours() {
return 40; // works 40 hours / week
}

public double getSalary() {


return 40000.0; // $40,000.00 / year
}

public int getVacationDays() {


return 10; // 2 weeks' paid vacation
}

public String getVacationForm() {


return "yellow"; // use the yellow form
}

public void takeDictation(String text) {


System.out.println("Taking dictation of text: " + text);
}
}
7
How are they similar?
// A class to represent employees // A class to represent secretaries
public class Employee { public class Secretary {
public int getHours() { public int getHours() {
return 40; return 40;
} }

public double getSalary() { public double getSalary() {


return 40000.0; return 40000.0;
} }

public int getVacationDays() { public int getVacationDays() {


return 10; return 10;
} }

public String getVacationForm() { public String getVacationForm() {


return "yellow"; return "yellow";
} }
}
public void takeDictation(String text) {
System.out.println("Taking dictation of text: "
+ text);
}
}

8
Is-a relationship

 is-a relationship: A hierarchical connection where


one category can be treated as a specialized
version of another.

 Examples:
 Every secretary is an employee.
 Every square is a rectangle.
 Every dog is a mammal.

9
Reusing code: why re-invent the wheel?

 code reuse: The practice of writing program code once and using it
in many contexts.

 We'd like to be able to say the following:


// A class to represent secretaries
public class Secretary {
<copy all the contents from Employee class>

public void takeDictation(String text) {


System.out.println("Taking dictation of text: "
+ text);
}
}

 That way we would be reusing the Employee code.


10
Inheritance

 inheritance: A way to specify a relationship


between two classes where one class inherits the
state and behavior of another.

 The child class (also called subclass) inherits from


the parent class (also called superclass).

 The subclass receives a copy of every field and


method from the superclass.

11
Inheritance syntax

 Creating a subclass, general syntax:


public class <subclass name> extends <superclass name>

 Example:
public class Secretary extends Employee
{
....
}

 By extending Employee, each Secretary object


automatically has a getHours, getSalary,
getVacationDays, and getVacationForm method.
12
Improved Secretary class
// A class to represent secretaries
public class Secretary extends Employee
{
public void takeDictation(String text) {
System.out.println("Taking dictation of text: "
+ text);
}
}

13
Writing even more classes

 Write a Marketer class that represents marketers


who have the same properties as general employees,
but instead of making only a paltry $40,000, marketers
make $50,000!

 Can we still leverage the Employee class or do we


have to re-write everything, because one method
(getSalary) is different?

 If only Marketer could write a new version of the


getSalary method, but inherit everything else…

14
Overriding methods

 override: To write a new version of a method in a


subclass to replace the superclass's version.

 To override a superclass method, just write a new


version of it in the subclass. This will replace the
inherited version.

15
Marketer class
// A class to represent marketers
public class Marketer extends Employee {
public void advertise() {
System.out.println("Act now while supplies last!");
}

public double getSalary() {


//Employee e = new Employee();

return 50000.0
// + e.getSalary(); // $50,000.00 / year
}
}

16
Exercise: LegalSecretary

 Write a LegalSecretary class that represents


legal secretaries—a special type of secretary that
can file legal briefs. Legal secretaries also earn
more money ($45,000).

17
Solution: LegalSecretary
// A class to represent legal secretaries
public class LegalSecretary extends Secretary {
public void fileLegalBriefs() {
System.out.println("I could file all day!");
}

public double getSalary() {


return 45000.0; // $45,000.00 / year
}
}

18
Inheritance hierarchies

 Deep hierarchies can be created by multiple levels


of subclassing.

 inheritance hierarchy: A set of classes connected


by is-a relationships that can share common code.

Indirect
Subclass

Direct
Subclass

19
Exercise: Lawyer

 Lawyers are employees that know how to sue.


They get an extra week of paid vacation (a total of
3) and have to use the pink form when applying for
vacation leave. Write the Lawyer class.

20
Solution: Lawyer
// A class to represent lawyers
public class Lawyer extends Employee {
// overrides getVacationForm from Employee class
public String getVacationForm() {
return "pink";
}

// overrides getVacationDays from Employee class


public int getVacationDays() {
return 15; // 3 weeks vacation
}

public void sue() {


System.out.println("I'll see you in court!");
}
}

21
Object class
Some Questions about Inheritance

 All classes in Java are direct or indirect subclasses of one


class. What is it?
 The Object class

 Explain why the designers of Java decided this was a


good idea.
 All classes share functionality! What is it?

23
The Object Class

Method Description
String toString() Returns a String description of the object.
boolean equals(Object other) Returns true if this and other point to the
same address.
Object clone() Returns a copy of this.
Class getClass() Returns a Class object representing the data
type (Class) of this.
Several others See Java API documentation …

Because every class automatically extends Object,


and because Object defines these methods,

 every class automatically has these methods!


24
A closer look at these methods

 The Object class already defines toString()


 And every class inherits from Object
 So why do we ever define our own toString()?
 Because the default Object methods are basically
placeholders!
 They don’t do anything very useful.
Example: Course
public class Course {
String [] students;
public Course(String [] students)
{ this.students = students; }

public static void main(String [] args)


throws CloneNotSupportedException {
String [] s1 = {“Jill”,”Jim”,”Joe”};
String [] s2 = {“Jill”,”Jim”,”Joe”};
Course c1 = new Course(s1);
Course c2 = new Course(s2);
System.out.println(c1.toString());
System.out.println(“c1 equals c2: “ + c1.equals(c2));
Course c3 = c1.clone();
System.out.println(“c1 == c3: “ + (c1==c3));
System.out.println(“c1 equals c3: “ + c1.equals(c3));
}
}
Output of Course

> java Course


Course@187aeca
c1 equals c2: false
Exception in thread “main”
java.lang.CloneNotSupportedException:
Course

Overriding

 It’s a good idea to override Object methods for any new


class!

 Example: overriding toString()

import java.util.Arrays;

public String toString()
{
return "Student list: " +
Arrays.toString(students);
}
Overriding the equals method

 toString() is the easy case. Let’s take a look at equals()

 Will this work?


public boolean equals(Course other)
{
return this==other;
}
Overriding the equals method,
Take 2

 Ok, how about this?

public boolean equals(Course other)


{
if(other==null) {
return false;
}
return this.students == other.students;
}
Overriding the equals method,
Take 3

 Ok, how about this?


public boolean equals(Course other)
{
if(other==null) {
return false;
}
if(this.students==null && other.students==null) {
return true;
}
if(this.students!=null) {
return this.students.equals(other.students);
}
return false;
}
Deep vs. Shallow Comparisons

 A shallow comparison
 checks to see if two objects have fields with the same
references:

this.students == other.students

 A deep comparison
 checks to see if two objects have fields with the same
contents:

this.students.equals(other.students)
Exercise: Overriding clone()

 First, override the clone() method for Course so that if we


call Course c2 = c1.clone(), then c2.students ==
c1.students (shallow clone).

 Now, override the clone() method for Course so that if we


call Course c2 = c1.clone(), then c2.equals(c1), but
c2.students != c1.students (deep clone).
super?
Constructor for superclass

public class Employee {


private double salary;
public Employee(double initialSalary)
{
salary = initialSalary;
}
public int getHours() {
return 40; // 40 hours per week
}
public double getSalary() {
return salary;
}
public int getVacationDays() {
return 10; // 2 weeks' paid vacation
}
public String getVacationForm() {
return "yellow"; // use the yellow form
}
}

35
Constructors of subclasses

Use the super() method to call the superclass’s constructor

public class Marketer extends Employee {


// inherits double salary

public Marketer(double initialSalary)


{
//construct superclass
super(initialSalary);
}
}

- For every constructor of a subclass, the call to super() must be the


first statement in the subclass’s constructor.
- Make sure to give the same number of arguments as there are
parameters in the definition of the superclass’s constructor.
protected
Do you have protection?

 Recall: there are four access specifiers:


public private protected <default>
 Question: If a method is declared private, does a
subclass inherit it?
 Actually, yes. Subclasses inherit everything that they don’t
override.
 If a method is declared private, can a subclass call it?
 NO! Only code inside the same class can call a private
method.
 What if you want a subclass to be able to use it?
 Use the protected access level

38
Access Specifier Example

 Recall our new Employee class

public class Employee {


private double salary = 40000.00;

public int getHours() {


return 40; // works 40 hours / week
}

public double getSalary() {


return salary;
}

public int getVacationDays() {


return 10; // 2 weeks' paid vacation
}

public String getVacationForm() {


return "yellow"; // use the yellow form
}
}
39
Access Specifier Example, continued

 Subclasses cannot see salary directly!

public class CEO extends Employee {


public void giveMyselfRaise() {
salary += 1000000.00; // Compile-time Error!
}
public static void main(String [] args)
{
CEO c = new CEO();
// This is fine, no error here
// Access to salary field is indirect
// We’re accessing the public getSalary() method
System.out.println(“My salary is “ + c.getSalary());
}
}

40
Access Specifier Example, continued
 If we want subclasses (and nothing else) to see
something, make it protected:
public class Employee {
protected double salary = 40000.00;
public int getHours() {
return 40; // works 40 hours / week
}
public double getSalary() {
return salary;
}
public int getVacationDays() {
return 10; // 2 weeks' paid vacation
}
public String getVacationForm() {
return "yellow"; // use the yellow form
}
}
41
Access Specifier Example, continued

 Subclasses can see protected variables and methods


just fine.

public class CEO extends Employee {


public void giveMyselfRaise() {
salary += 1000000.00; // No longer an error
}
public static void main(String [] args)
{
CEO c = new CEO();
// This is fine, no error here
// Access to salary field is indirect
// We’re accessing the public getSalary() method
System.out.println(“My salary is “ + c.getSalary());
}
}

42
What would happen if ....

public class Employee {


private double salary = 40000.00;

public int getHours() {


return 40; // works 40 hours / week
}

public double getSalary() {


return salary;
}

public void addToSalary(double raise) {


salary += raise;
}

public int getVacationDays() {


return 10; // 2 weeks' paid vacation
}

public String getVacationForm() {


return "yellow"; // use the yellow form
}
}
43
What would happen if ... (continued)

public class CEO extends Employee {

public void giveMyselfRaise() {


addToSalary(1000000.00); // Error??
}
}

 CEO still has its own copy of the salary field, and this
code will change the value of it appropriately.
 The fact that salary is private simply means that CEO
can't access it directly. It can still call public (or protected)
superclass methods that can access it.

44
final

(the keyword, not the exam)

45
Motivation

 Suppose we’ve defined an Employee class, and we


don’t want someone to come along and muck it up
 E.g., we don’t want a CEO subclass that gives itself a raise

 The final keyword indicates that some definition


(of a class, method, or field) cannot be changed or
overridden by a subclass.

46
final Example
// A class to represent employees
public class Employee {
public int getHours() {
return 40; // works 40 hours / week
}

public final double getSalary() {


return 40000.0; // $40,000.00 / year
}

public int getVacationDays() {


return 10; // 2 weeks' paid vacation
}

public String getVacationForm() {


return "yellow"; // use the yellow form
}
}
No subclass is allowed to change the definition of getSalary()!
47
final fields, methods, and classes

The final keyword can be applied to fields (as we’ve seen before):
// no code may change the value of salary,
//including a subclass’s code
public final double salary = 40000.0;

Or to methods:
// subclasses cannot override the getSalary method
public final double getSalary() { return salary; }

Or even to classes:
// the Employee class cannot be extended
// It can’t have any subclasses at all!
public final class Employee { ... }

48
Exercise: Update the Employee
class

 Add final declarations to the Employee class below so


that different subclasses can have different salaries, but
once their salary is set, they can’t be changed.
public class Employee {
private double salary;
public Employee(int sal)
{
salary = sal;
}

public double getSalary() {


return salary;
}
}
abstract

50
Opposite of final

 The final keyword prevents subclasses from changing


(overriding) code

 Sometimes, you want to do the opposite:

Force another programmer or piece of code


to finish parts of a class.
Example: Employee salary

 Let’s say you want every subclass of Employee to have a


salary, but you want the subclass to decide what the
salary should be.

 We can define an “abstract” getSalary() method:


public abstract double getSalary();

 Note: no method definition!


 Abstract method declarations don’t provide definitions, just signatures.
 They are there to force subclasses to provide the definitions.
Abstract Rules (1)

1. If a class has an abstract method, or it inherits an


abstract method that it doesn’t override,
then the class must be declared abstract.

public abstract class Employee {


public abstract double getSalary();

// you can mix abstract and non-abstract methods


// in an abstract class
public int getHours() { // Note: not abstract!
return 40;
}
}
Abstract Rules (2)

2. If a class is abstract, it can’t have a constructor.


 No Employee object can be constructed
 But you can declare Employee references.

public abstract class Employee {


public abstract double getSalary();

public static void main(String [] args) {


Employee e; // NO ERROR: reference is fine
e = new Employee(); // ERROR! No constructor
}
}
Extending an abstract class

public class Lawyer extends Employee {


// since Employee declares an abstract getSalary,
// Lawyer must define getSalary by overriding it
// or else Lawyer must be an abstract class
public double getSalary() {
return 45000.0;
}

public static void main(String [] args) {


Employee e; // Fine, no problem
e = new Lawyer(); // Also fine (polymorphism)
e = new Employee(); // ERROR! No constructor!
}
}
Abstract classes: what’s the point?

 If you can’t construct objects for a class, what’s the point


of the class? How can we use it?
 Short Answer: polymorphism.
 We can use references of type Employee as a place to
store Lawyers, Secretaries, CEOs, etc.
 Because getSalary() is declared in Employee, e.getSalary()
is legal syntax, even though getSalary() is not defined in
Employee.
Interfaces

Completely abstract.

57
Going full abstract

 What if our abstract class had no non-abstract methods?

public abstract class Employee {


public abstract double getSalary();
public abstract int getHours();
public abstract String getVacationForm();
}

Each subclass would have different definitions.


They share only the names of their methods.
Java has an alternative way to do this:
interfaces
58
Interfaces

 Let's say you have the following two related classes:

public class Scientist { public class Engineer {


public void discover() { public void discover() {
System.out.println(“Eureka! System.out.println(“Cool,
I have found it!“); what did I just do?“);
} }
public void publish() { public void publish() {
System.out.println(“My System.out.println(“I
research is better than don't know how this
yours.”); happened, but it works.”);
} }
} }

 Neither of their methods do the same thing.


59
Code Reuse

 But they're still similar – they both discover and publish.


Can we get code reuse?

interface Researcher {
void discover();
void publish();
}

 But why? What does that accomplish?


 Now we can create Researcher references

60
Using Interface Objects
public static void researchCycle(Researcher r) {
r.discover();
r.publish();
}

public static void main(String [] args) {


Researcher researcher1 = new Scientist();
Researcher researcher2 = new Engineer();
// Interfaces have no constructors
// They can only be used as types for references
researcher2 = new Researcher(); // ERROR!

researchCycle(researcher1);
researchCycle(researcher2);
}

61
Using Interfaces

 Interfaces are a way of specifying what objects are


capable of, without saying how.

 Interface variables can execute any of the methods listed


in the interface, but the behavior depends on the class of
the object
 That is, interface variables are polymorphic.

 There are no constructors for interfaces. They are not


classes, and no objects of that run-time type are created.
They are compile-time types for references.
62
Implementing Interfaces
public class Scientist implements Researcher {

public void discover() {


System.out.println(“Eureka! I have found it!“);
}

public void publish() {


System.out.println(“My research is better than yours.”);
}
}

63
Implementing Interfaces
public class Engineer implements Researcher {
public void discover() {
System.out.println(“Whoa, what did I just do?“);
}

public void publish() {


System.out.println(“I don't know how this happened, but
it works.”);
}
}

64
Creating Custom Interfaces
public interface Edible {
/** Describe how to eat */ class abstract Fruit
public String howToEat(); implements Edible {
} }

class Animal { class Apple extends Fruit {


} public String howToEat() {
return "Make apple cider";
class Chicken extends Animal }
implements Edible { }
public String howToEat() {
return "Fry it"; class Orange extends Fruit {
} public String howToEat() {
} return "Make orange juice";
}
class Tiger extends Animal { }
}

65
Implements Multiple Interfaces

class Chicken extends Animal implements Edible, Comparable {


int weight;
public Chicken(int weight) {
this.weight = weight;
}
public String howToEat() {
return "Fry it";
}
public int compareTo(Object o) {
return weight – ((Chicken)o).weight;
}
}

66
Creating Custom Interfaces, cont.
public interface Edible {
/** Describe how to eat */
public String howToEat();
}

public class TestEdible {


public static void main(String[] args) {
Object[] objects = {new Tiger(), new Chicken(), new Apple()};
for (int i = 0; i < objects.length; i++)
showObject(objects[i]);
}

public static void showObject(Object object) {


if (object instanceof Edible)
System.out.println(((Edible)object).howToEat());
}
}

67
Exercise: Comparable interface

 Define the Comparable interface

public interface Comparable {


public int compareTo(Object other);
}

public interface Comparable<T> {


public int compareTo(T other);
}
Exercise: Dataset with Interfaces

 Below is a dataset class that finds the maximum and


average of a set of ints.

 Modify the dataset class so that it works for any class


which implements the right interface (that you define).

 Create a BankAccount class that implements your


interface, and use Dataset to find the BankAccount with
the maximum balance.
Dataset class (to be modified)

public class Dataset


{
private int count = 0;
private int maximum = Integer.MIN_INT;
private double sum = 0;
public void add(int x) {
sum += x;
count++;
if(x > maximum) { maximum = x; }
}
public int getMaximum() { return maximum; }
public double getAvg() { return sum / count; }
}
BankAccount (to be modified)

public class BankAccount {


private double balance = 0;

public BankAccount(double initBalance) {


balance = initBalance;
}
public double getBalance() { return balance; }

public static BankAccount getMaxAcct(


BankAccount [] accounts)
{
// fill this in!
}
}
BankAccount (solution)
public class BankAccount implements Measurable {
private int balance = 0;
public BankAccount(int initBalance) {
balance = initBalance;
}
public int getBalance() { return balance; }
public int getMeasure() {
return getBalance();
}
public BankAccount getMaxAcct(BankAccount [] accounts) {
Dataset d = new Dataset();
for(int i=0; i<accounts.length; i++) {
d.add(accounts[i]);
}
return (BankAccount)d.getMaximum();
}
}

You might also like