1 of 68

Interface and Implementation Inheritance

1

Lecture 8 (Inheritance 1)

CS61B, Fall 2023 @ UC Berkeley

Slides credit: Josh Hug

2 of 68

The Desire for Generality

Lecture 8, CS61B, Fall 2023

Interface Inheritance

  • The Desire for Generality
  • Hypernyms and Hyponyms
  • Interface and Implements Keywords
  • Overriding vs. Overloading
  • Interface Inheritance

Implementation Inheritance

  • Default Methods
  • Overriding Default Methods

Static and Dynamic Type

  • Static and Dynamic Type
  • Changes to Scope in 61B

Using Inheritance Safely

3 of 68

AList and SLList

After adding an additional “insert” method. Our AList and SLList classes from lecture have the following methods (exact same method signatures for both classes).

public class AList<Item>{

public AList()

public void insert(Item x, int position)

public void addFirst(Item x)

public void addLast(Item i)

public Item getFirst()

public Item getLast()

public Item get(int i)

public int size()

public Item removeLast()

}

public class SLList<Blorp>{

public SLList()

public SLList(Blorp x)

public void insert(Blorp item, int position)

public void addFirst(Blorp x)

public void addLast(Blorp x)

public Blorp getFirst()

public Blorp getLast()

public Blorp get(int i)

public int size()

public Blorp removeLast()

}

4 of 68

Using ALists and SLLists: WordUtils.java

Suppose we’re writing a library to manipulate lists of words. Might want to write a function that finds the longest word from a list of words:

public static String longest(SLList<String> list) {

int maxDex = 0;

for (int i = 0; i < list.size(); i += 1) {

String longestString = list.get(maxDex);

String thisString = list.get(i);

if (thisString.length() > longestString.length()) {

maxDex = i;

}

}

return list.get(maxDex);

}

Observant viewers may note this code is very inefficient! Don’t worry about it.

5 of 68

Demo: Using ALists and SLLists

This example usage of the longest method works fine.

public static String longest(SLList<String> list) {

...

}

public static void main(String[] args) {

SLList<String> someList = new SLList<>();

someList.addLast("elk");

someList.addLast("are");

someList.addLast("watching");

System.out.println(longest(someList));

}

watching

WordUtils.java

6 of 68

Demo: Using ALists and SLLists

What if somebody placed their list of words in an AList instead of an SLList?

public static String longest(SLList<String> list) {

...

}

public static void main(String[] args) {

AList<String> someList = new AList<>();

someList.addLast("elk");

someList.addLast("are");

someList.addLast("watching");

System.out.println(longest(someList));

}

AList instead of SLList.

WordUtils.java

7 of 68

Demo: Using ALists and SLLists

What if somebody placed their list of words in an AList instead of an SLList?

public static String longest(SLList<String> list) {

...

}

public static void main(String[] args) {

AList<String> someList = new AList<>();

someList.addLast("elk");

someList.addLast("are");

someList.addLast("watching");

System.out.println(longest(someList));

}

Compiler error:

SLList cannot be applied to AList.

WordUtils.java

8 of 68

Using ALists and SLLists: WordUtils.java

If we want longest to be able to handle ALists, what changes do we need to make?

public static String longest(SLList<String> list) {

int maxDex = 0;

for (int i = 0; i < list.size(); i += 1) {

String longestString = list.get(maxDex);

String thisString = list.get(i);

if (thisString.length() > longestString.length()) {

maxDex = i;

}

}

return list.get(maxDex);

}

9 of 68

Using ALists and SLLists: WordUtils.java

If we want longest to be able to handle ALists, what changes do we need to make?

public static String longest(AList<String> list) {

int maxDex = 0;

for (int i = 0; i < list.size(); i += 1) {

String longestString = list.get(maxDex);

String thisString = list.get(i);

if (thisString.length() > longestString.length()) {

maxDex = i;

}

}

return list.get(maxDex);

}

10 of 68

Method Overloading in Java

Java allows multiple methods with same name, but different parameters.

  • This is called method overloading.

public static String longest(AList<String> list) {

...

}

public static String longest(SLList<String> list) {

...

}

Possible solution: Copy-paste the same method body into two methods with different signatures.

11 of 68

The Downsides

While overloading works, it is a bad idea in the case of longest. Why?

  • Code is virtually identical. Aesthetically gross.
  • Won’t work for future lists. If we create a QList class, have to make a third method.
  • Harder to maintain.
    • Example: Suppose you find a bug in one of the methods. You fix it in the SLList version, and forget to do it in the AList version.

12 of 68

Hypernyms and Hyponyms

Lecture 8, CS61B, Fall 2023

Interface Inheritance

  • The Desire for Generality
  • Hypernyms and Hyponyms
  • Interface and Implements Keywords
  • Overriding vs. Overloading
  • Interface Inheritance

Implementation Inheritance

  • Default Methods
  • Overriding Default Methods

Static and Dynamic Type

  • Static and Dynamic Type
  • Changes to Scope in 61B

Using Inheritance Safely

13 of 68

Hypernyms

In natural languages (English, Spanish, Chinese, Tagalog, etc.), we have a concept known as a “hypernym” to deal with this problem.

  • Dog is a “hypernym” of poodle, malamute, yorkie, etc.

Washing your poodle:

1. Brush your poodle before a bath. ...

2. Use lukewarm water. ...

3. Talk to your poodle in a calm voice. ...

4. Use poodle shampoo. ...

5. Rinse well. ...

6. Air-dry. ...

7. Reward your poodle.

Washing your malamute:

1. Brush your malamute before a bath. ...

2. Use lukewarm water. ...

3. Talk to your malamute in a calm voice. ...

4. Use malamute shampoo. ...

5. Rinse well. ...

6. Air-dry. ...

7. Reward your malamute.

14 of 68

Hypernyms

In natural languages (English, Spanish, Chinese, Tagalog, etc.), we have a concept known as a “hypernym” to deal with this problem.

  • Dog is a “hypernym” of poodle, malamute, yorkie, etc.

Washing your poodle:

1. Brush your poodle before a bath. ...

2. Use lukewarm water. ...

3. Talk to your poodle in a calm voice. ...

4. Use poodle shampoo. ...

5. Rinse well. ...

6. Air-dry. ...

7. Reward your poodle.

Washing your malamute:

1. Brush your malamute before a bath. ...

2. Use lukewarm water. ...

3. Talk to your malamute in a calm voice. ...

4. Use malamute shampoo. ...

5. Rinse well. ...

6. Air-dry. ...

7. Reward your malamute.

Washing your dog:

1. Brush your dog before a bath. ...

2. Use lukewarm water. ...

3. Talk to your dog in a calm voice. ...

4. Use dog shampoo. ...

5. Rinse well. ...

6. Air-dry. ...

7. Reward your dog.

15 of 68

Hypernym and Hyponym

We use the word hyponym for the opposite type of relationship.

  • “dog”: Hypernym of “poodle”, “malamute”, “dachshund”, etc.
  • “poodle”: Hyponym of “dog”

Hypernyms and hyponyms comprise a hierarchy.

  • A dog “is-a” canine.
  • A canine “is-a” carnivore.
  • A carnivore “is-an” animal.

(for fun: see the WordNet project)

animal

omnivore

herbivore

carnivore

feline

canine

dog

16 of 68

Interface and Implements Keywords

Lecture 8, CS61B, Fall 2023

Interface Inheritance

  • The Desire for Generality
  • Hypernyms and Hyponyms
  • Interface and Implements Keywords
  • Overriding vs. Overloading
  • Interface Inheritance

Implementation Inheritance

  • Default Methods
  • Overriding Default Methods

Static and Dynamic Type

  • Static and Dynamic Type
  • Changes to Scope in 61B

Using Inheritance Safely

17 of 68

Simple Hyponymic Relationships in Java

SLLists and ALists are both clearly some kind of “list”.

  • List is a hypernym of SLList and AList.

Expressing this in Java is a two-step process:

  • Step 1: Define a reference type for our hypernym (List61B.java).
  • Step 2: Specify that SLLists and ALists are hyponyms of that type.�

List61B

SLList

AList

18 of 68

Step 1: Defining a List61B

We’ll use the new keyword interface instead of class to define a List61B.

  • Idea: Interface is a specification of what a List is able to do, not how to do it.

19 of 68

Step 1: Defining a List61B

We’ll use the new keyword interface instead of class to define a List61B.

  • Idea: Interface is a specification of what a List is able to do, not how to do it.

public interface List61B<Item> {

public void insert(Item x, int position);

public void addFirst(Item x);

public void addLast(Item y);

public Item getFirst();

public Item getLast();

public Item removeLast();

public Item get(int i);

public int size();

}

List61B.java

List61B

20 of 68

Step 2: Implementing the List61B Interface

We’ll now:

  • Use the new implements keyword to tell the Java compiler that SLList and AList are hyponyms of List61B.

public class AList<Item> implements List61B<Item> {

...

public void addLast(Item x) {

...

List61B

AList

21 of 68

Step 2: Implementing the List61B Interface

We’ll now:

  • Use the new implements keyword to tell the Java compiler that SLList and AList are hyponyms of List61B.

public class SLList<Blorp> implements List61B<Blorp>{

...

public void addLast(Blorp x) {

...

List61B

SLList

AList

22 of 68

Adjusting WordUtils.java

We can now adjust our longest method to work on either kind of list:

public static String longest(List61B<String> list) {

int maxDex = 0;

for (int i = 0; i < list.size(); i += 1) {

String longestString = list.get(maxDex);

String thisString = list.get(i);

if (thisString.length() > longestString.length()) {

maxDex = i;

}

}

return list.get(maxDex);

}

AList<String> a = new AList<>();

a.addLast("egg");

a.addLast("boyz");

longest(a);

23 of 68

Demo: Interface and Implements Keywords

Our longest method now takes in a List61B (not a SLList or AList).

public static String longest(List61B<String> list) {

...

}

public static void main(String[] args) {

SLList<String> someList = new SLList<>();

someList.addLast("elk");

someList.addLast("are");

someList.addLast("watching");

System.out.println(longest(someList));

}

watching

WordUtils.java

…including SLList.

You can pass in any object that implements List61B…

24 of 68

Demo: Interface and Implements Keywords

Our longest method now takes in a List61B (not a SLList or AList).

public static String longest(List61B<String> list) {

...

}

public static void main(String[] args) {

AList<String> someList = new AList<>();

someList.addLast("elk");

someList.addLast("are");

someList.addLast("watching");

System.out.println(longest(someList));

}

watching

WordUtils.java

…including AList.

You can pass in any object that implements List61B…

25 of 68

Overriding vs. Overloading

Lecture 8, CS61B, Fall 2023

Interface Inheritance

  • The Desire for Generality
  • Hypernyms and Hyponyms
  • Interface and Implements Keywords
  • Overriding vs. Overloading
  • Interface Inheritance

Implementation Inheritance

  • Default Methods
  • Overriding Default Methods

Static and Dynamic Type

  • Static and Dynamic Type
  • Changes to Scope in 61B

Using Inheritance Safely

26 of 68

Method Overriding

If a “subclass” has a method with the exact same signature as in the “superclass”, we say the subclass overrides the method.

public class AList<Item> implements List61B<Item>{

...

public void addLast(Item x) {

...

public interface List61B<Item> {

public void addLast(Item y);

...

AList overrides addLast(Item)

27 of 68

Method Overriding vs. Overloading

If a “subclass” has a method with the exact same signature as in the “superclass”, we say the subclass overrides the method.

  • Animal’s subclass Pig overrides the makeNoise() method.

public class Dog implements Animal {

public void makeNoise(Dog x)

public void makeNoise()

makeNoise is overloaded

public interface Animal {

public void makeNoise();

}

public class Pig implements Animal {

public void makeNoise() {

System.out.print("oink");

}

}

Pig overrides makeNoise()

public class Math {

public int abs(int a)

public double abs(double a)

abs is overloaded

  • Methods with the same name but different signatures are overloaded.

28 of 68

Optional Step 2B: Adding the @Override Annotation

In 61b, we’ll always mark every overriding method with the @Override annotation.

  • Example: Mark AList.java’s overriding methods with @Override.
  • The only effect of this tag is that the code won’t compile if it is not actually an overriding method.

public class AList<Item> implements List61B<Item>{

...

@Override

public void addLast(Item x) {

...

List61B

SLList

AList

29 of 68

Method Overriding

If a subclass has a method with the exact same signature as in the superclass, we say the subclass overrides the method.

  • Even if you don’t write @Override, subclass still overrides the method.
  • @Override is just an optional reminder that you’re overriding.

Why use @Override?

  • Main reason: Protects against typos.
    • If you say @Override, but it the method isn’t actually overriding anything, you’ll get a compile error.
    • e.g. public void addLats(Item x)
  • Reminds programmer that method definition came from somewhere higher up in the inheritance hierarchy.

30 of 68

Interface Inheritance

Lecture 8, CS61B, Fall 2023

Interface Inheritance

  • The Desire for Generality
  • Hypernyms and Hyponyms
  • Interface and Implements Keywords
  • Overriding vs. Overloading
  • Interface Inheritance

Implementation Inheritance

  • Default Methods
  • Overriding Default Methods

Static and Dynamic Type

  • Static and Dynamic Type
  • Changes to Scope in 61B

Using Inheritance Safely

31 of 68

Interface Inheritance

Specifying the capabilities of a subclass using the implements keyword is known as interface inheritance.

  • Interface: The list of all method signatures.
  • Inheritance: The subclass “inherits” the interface.
  • Specifies what the subclass can do, but not how.
  • Subclasses must override all of these methods!
    • Will fail to compile otherwise.

List61B

SLList

AList

public interface List61B<Item> {

public void addFirst(Item x);

...

public void proo();

}

If AList doesn’t have a proo() method, AList will not compile!

32 of 68

Interface Inheritance

Specifying the capabilities of a subclass using the implements keyword is known as interface inheritance.

  • Interface: The list of all method signatures.
  • Inheritance: The subclass “inherits” the interface.
  • Specifies what the subclass can do, but not how.
  • Subclasses must override all of these methods!
  • Such relationships can be multi-generational.
    • Figure: Interfaces in white, classes in green.
    • We’ll talk about this in a later lecture.

Interface inheritance is a powerful tool for generalizing code.

  • WordUtils.longest works on SLLists, ALists, and even lists that have not yet been invented!

Collection61B

List61B

SLList

AList

33 of 68

Is-a-relationships

Recall: A memory box can only hold 64 bit addresses for the appropriate type.

  • Example: inputList can only hold a List61B<String>.
  • An AList is-a List61B, so inputList can hold a reference to the AList.

public static String longest(List61B<String> inputList) {

int maxDex = 0;

for (int i = 0; i < inputList.size(); i += 1)

...

public static void main(String[] args) {

AList<String> a1 = new AList<String>();

a1.addLast("horse");

WordUtils.longest(a1);

}

Allowed! An AList is a List61B.

34 of 68

Question: yellkey.com/TODO

Will the code below compile? If so, what happens when it runs?

  1. Will not compile.
  2. Will compile, but will cause an error at runtime on the new line.
  3. When it runs, an SLList is created and its address is stored in the someList variable, but it crashes on someList.addFirst() since the List interface doesn’t implement addFirst.
  4. When it runs, an SLList is created and its address is stored in the someList variable. Then the string “elk” is inserted into the SLList referred to by addFirst.

public static void main(String[] args) {

List61B<String> someList = new SLList<String>();

someList.addFirst("elk");

}

35 of 68

Question

Will the code below compile? If so, what happens when it runs?

  • Will not compile.
  • Will compile, but will cause an error at runtime on the new line.
  • When it runs, an SLList is created and its address is stored in the someList variable, but it crashes on someList.addFirst() since the List interface doesn’t implement addFirst.
  • When it runs, an SLList is created and its address is stored in the someList variable. Then the string “elk” is inserted into the SLList referred to by addFirst.

public static void main(String[] args) {

List61B<String> someList = new SLList<String>();

someList.addFirst("elk");

}

36 of 68

Default Methods

Lecture 8, CS61B, Fall 2023

Interface Inheritance

  • The Desire for Generality
  • Hypernyms and Hyponyms
  • Interface and Implements Keywords
  • Overriding vs. Overloading
  • Interface Inheritance

Implementation Inheritance

  • Default Methods
  • Overriding Default Methods

Static and Dynamic Type

  • Static and Dynamic Type
  • Changes to Scope in 61B

Using Inheritance Safely

37 of 68

Implementation Inheritance

Interface inheritance:

  • Subclass inherits signatures, but NOT implementation.�

For better or worse, Java also allows implementation inheritance.

  • Subclasses can inherit signatures AND implementation.

Use the default keyword to specify a method that subclasses should inherit from an interface.

  • Example: Let’s add a default print() method to List61B.java

38 of 68

Coding Demo: Default Methods

public interface List61B<Item> {

public Item get(int i);

public int size();

/** Prints out the entire list. */

public void print() {

}

}

List61B.java

If we try to write a method like we normally do in a class, we get an error:

"Interface methods cannot have body"

39 of 68

Coding Demo: Default Methods

public interface List61B<Item> {

public Item get(int i);

public int size();

/** Prints out the entire list. */

default public void print() {

}

}

List61B.java

If we add the default keyword, the error goes away. Now we can write a method body in the interface.

40 of 68

Coding Demo: Default Methods

public interface List61B<Item> {

public Item get(int i);

public int size();

/** Prints out the entire list. */

default public void print() {

for (int i = 0; i < size(); i += 1) {

}

}

}

List61B.java

41 of 68

Coding Demo: Default Methods

public interface List61B<Item> {

public Item get(int i);

public int size();

/** Prints out the entire list. */

default public void print() {

for (int i = 0; i < size(); i += 1) {

System.out.print(get(i) + " ");

}

}

}

List61B.java

42 of 68

Coding Demo: Default Methods

public interface List61B<Item> {

public Item get(int i);

public int size();

/** Prints out the entire list. */

default public void print() {

for (int i = 0; i < size(); i += 1) {

System.out.print(get(i) + " ");

}

System.out.println();

}

}

List61B.java

43 of 68

Coding Demo: Default Methods

public class IsADemo {

public static void main(String[] args) {

List61B<String> someList = new SLList<>();

someList.addFirst("elk");

someList.addLast("dwell");

someList.addLast("on");

someList.addLast("existential");

someList.addLast("crises");

someList.print();

}

}

IsADemo.java

elk dwell on existential crises

SLLists don't have a print method, but the print method still works.

The default print method in the List61B interface is executed.

44 of 68

Default Method Example: print()

public interface List61B<Item> {

public void insert(Item x, int position);

public void addFirst(Item x);

public void addLast(Item x);

public Item getFirst();

public Item getLast();

public Item get(int i);

public int size();

public Item removeLast();

default public void print() {

for (int i = 0; i < size(); i += 1) {

System.out.print(get(i) + " ");

}

System.out.println();

}

}

45 of 68

Question: yellkey.com/TODO

Is the print() method efficient?

  1. Inefficient for AList and SLList
  2. Efficient for AList, inefficient for SLList
  3. Inefficient for AList, efficient for SLList
  4. Efficient for both AList and SLList

public interface List61B<Item> {

...

default public void print() {

for (int i = 0; i < size(); i += 1) {

System.out.print(get(i) + " ");

}

System.out.println();

}

}

46 of 68

Overriding Default Methods

Lecture 8, CS61B, Fall 2023

Interface Inheritance

  • The Desire for Generality
  • Hypernyms and Hyponyms
  • Interface and Implements Keywords
  • Overriding vs. Overloading
  • Interface Inheritance

Implementation Inheritance

  • Default Methods
  • Overriding Default Methods

Static and Dynamic Type

  • Static and Dynamic Type
  • Changes to Scope in 61B

Using Inheritance Safely

47 of 68

Question

Is the print() method efficient?

  • Inefficient for AList and SLList
  • Efficient for AList, inefficient for SLList
  • Inefficient for AList, efficient for SLList
  • Efficient for both AList and SLList

public interface List61B<Item> {

...

default public void print() {

for (int i = 0; i < size(); i += 1) {

System.out.print(get(i) + " ");

}

System.out.println();

}

}

get has to seek all the way to the given item for SLLists.

48 of 68

Coding Demo: Overriding Default Methods

public class SLList<Blorp> implements List61B<Blorp> {

/** A print method that overrides

* List61B's inefficient print method. */

public void print() {

}

}

SLList.java

49 of 68

Coding Demo: Overriding Default Methods

public class SLList<Blorp> implements List61B<Blorp> {

/** A print method that overrides

* List61B's inefficient print method. */

@Override

public void print() {

}

}

SLList.java

50 of 68

Coding Demo: Overriding Default Methods

public class SLList<Blorp> implements List61B<Blorp> {

/** A print method that overrides

* List61B's inefficient print method. */

@Override

public void print() {

for (Node p = sentinel.next; p != null; p = p.next) {

}

}

}

SLList.java

51 of 68

Coding Demo: Overriding Default Methods

public class SLList<Blorp> implements List61B<Blorp> {

/** A print method that overrides

* List61B's inefficient print method. */

@Override

public void print() {

for (Node p = sentinel.next; p != null; p = p.next) {

System.out.print(p.item + " ");

}

}

}

SLList.java

52 of 68

Coding Demo: Overriding Default Methods

public class SLList<Blorp> implements List61B<Blorp> {

/** A print method that overrides

* List61B's inefficient print method. */

@Override

public void print() {

System.out.println("The boss doesn't know what he's doing!");

for (Node p = sentinel.next; p != null; p = p.next) {

System.out.print(p.item + " ");

}

}

}

SLList.java

53 of 68

Coding Demo: Default Methods

public class IsADemo {

public static void main(String[] args) {

List61B<String> someList = new SLList<>();

someList.addFirst("elk");

someList.addLast("dwell");

someList.addLast("on");

someList.addLast("existential");

someList.addLast("crises");

someList.print();

}

}

IsADemo.java

The boss doesn't know what he's doing!

elk dwell on existential crises

Now we're running the print method in SLList, not the print method in List61B.

54 of 68

Overriding Default Methods

If you don’t like a default method, you can override it.

  • Any call to print() on an SLList will use this method instead of default.
  • Use (optional) @Override to catch typos like public void pirnt()

public class SLList<Blorp> implements List61B<Blorp> {

@Override

public void print() {

for (Node p = sentinel.next; p != null; p = p.next) {

System.out.print(p.item + " ");

}

System.out.println();

}

}

55 of 68

Question

Recall that if X is a superclass of Y, then an X variable can hold a reference to a Y.

Which print method do you think will run when the code below executes?

  • List.print()
  • SLList.print()

public static void main(String[] args) {

List61B<String> someList = new SLList<String>();

someList.addLast("elk");

someList.addLast("are");

someList.addLast("watching");

someList.print();

}

56 of 68

Question

Recall that if X is a superclass of Y, then an X variable can hold a reference to a Y.

Which print method do you think will run when the code below executes?

  • List.print()
  • SLList.print() : And this is the sensible choice. But how does it work?
    • Before we can answer that, we need new terms: static and dynamic type.

public static void main(String[] args) {

List61B<String> someList = new SLList<String>();

someList.addLast("elk");

someList.addLast("are");

someList.addLast("watching");

someList.print();

}

57 of 68

Static and Dynamic Type

Lecture 8, CS61B, Fall 2023

Interface Inheritance

  • The Desire for Generality
  • Hypernyms and Hyponyms
  • Interface and Implements Keywords
  • Overriding vs. Overloading
  • Interface Inheritance

Implementation Inheritance

  • Default Methods
  • Overriding Default Methods

Static and Dynamic Type

  • Static and Dynamic Type
  • Changes to Scope in 61B

Using Inheritance Safely

58 of 68

Static Type vs. Dynamic Type

Every variable in Java has a “compile-time type”, a.k.a. “static type”.

  • This is the type specified at declaration. Never changes!

�Variables also have a “run-time type”, a.k.a. “dynamic type”.

  • This is the type specified at instantiation (e.g. when using new).
  • Equal to the type of the object being pointed at.

public static void main(String[] args) {

LivingThing lt1;

lt1 = new Fox();

Animal a1 = lt1;

Fox h1 = new Fox();

lt1 = new Squid();

}

LivingThing

null

Static Type

Dynamic Type

lt1

LivingThing

Technically requires a “cast”. See next lecture.

59 of 68

Static Type vs. Dynamic Type

Every variable in Java has a “compile-time type”, a.k.a. “static type”.

  • This is the type specified at declaration. Never changes!

�Variables also have a “run-time type”, a.k.a. “dynamic type”.

  • This is the type specified at instantiation (e.g. when using new).
  • Equal to the type of the object being pointed at.

public static void main(String[] args) {

LivingThing lt1;

lt1 = new Fox();

Animal a1 = lt1;

Fox h1 = new Fox();

lt1 = new Squid();

}

LivingThing

Fox

Static Type

Dynamic Type

lt1

LivingThing

Technically requires a “cast”. See next lecture.

60 of 68

Static Type vs. Dynamic Type

Every variable in Java has a “compile-time type”, a.k.a. “static type”.

  • This is the type specified at declaration. Never changes!

�Variables also have a “run-time type”, a.k.a. “dynamic type”.

  • This is the type specified at instantiation (e.g. when using new).
  • Equal to the type of the object being pointed at.

public static void main(String[] args) {

LivingThing lt1;

lt1 = new Fox();

Animal a1 = lt1;

Fox h1 = new Fox();

lt1 = new Squid();

}

Technically requires a “cast”. See next lecture.

LivingThing

Fox

Static Type

Dynamic Type

Animal

Fox

lt1

a1

LivingThing

Animal

61 of 68

Static Type vs. Dynamic Type

Every variable in Java has a “compile-time type”, a.k.a. “static type”.

  • This is the type specified at declaration. Never changes!

�Variables also have a “run-time type”, a.k.a. “dynamic type”.

  • This is the type specified at instantiation (e.g. when using new).
  • Equal to the type of the object being pointed at.

public static void main(String[] args) {

LivingThing lt1;

lt1 = new Fox();

Animal a1 = lt1;

Fox h1 = new Fox();

lt1 = new Squid();

}

LivingThing

Fox

Static Type

Dynamic Type

lt1

Animal

Fox

Fox

Fox

a1

h1

LivingThing

Animal

Fox

62 of 68

Static Type vs. Dynamic Type

Every variable in Java has a “compile-time type”, a.k.a. “static type”.

  • This is the type specified at declaration. Never changes!

�Variables also have a “run-time type”, a.k.a. “dynamic type”.

  • This is the type specified at instantiation (e.g. when using new).
  • Equal to the type of the object being pointed at.

public static void main(String[] args) {

LivingThing lt1;

lt1 = new Fox();

Animal a1 = lt1;

Fox h1 = new Fox();

lt1 = new Squid();

}

LivingThing

Squid

Static Type

Dynamic Type

lt1

Animal

Fox

Fox

Fox

a1

h1

LivingThing

Animal

Fox

63 of 68

Dynamic Method Selection For Overridden Methods

Suppose we call a method of an object using a variable with:

  • compile-time type X
  • run-time type Y

�Then if Y overrides the method, Y’s method is used instead.

  • This is known as “dynamic method selection”.

This term is a bit obscure.

List61B

List61B

SLList

Static Type

Dynamic Type

public static void main(String[] args) {

LivingThing lt1;

lt1 = new Fox();

Animal a1 = lt1;

Fox h1 = new Fox();

lt1 = new Squid();

}

64 of 68

Changes to Scope in 61B

Lecture 8, CS61B, Fall 2023

Interface Inheritance

  • The Desire for Generality
  • Hypernyms and Hyponyms
  • Interface and Implements Keywords
  • Overriding vs. Overloading
  • Interface Inheritance

Implementation Inheritance

  • Default Methods
  • Overriding Default Methods

Static and Dynamic Type

  • Static and Dynamic Type
  • Changes to Scope in 61B

Using Inheritance Safely

65 of 68

Older Versions of 61B (pre-2018)

In older versions of this class, the section on Dynamic Method Selection included a tricky corner case where a subclass overloads (rather than overrides) a superclass method.

  • Even older versions went even deeper, showing what happens when subclasses have variables with the same name as their superclass.

Students spent a great deal of time on something that isn’t ultimately very important. This is not a class about Java minutiae, so I cut this material.

66 of 68

Using Inheritance Safely

Lecture 8, CS61B, Fall 2023

Interface Inheritance

  • The Desire for Generality
  • Hypernyms and Hyponyms
  • Interface and Implements Keywords
  • Overriding vs. Overloading
  • Interface Inheritance

Implementation Inheritance

  • Default Methods
  • Overriding Default Methods

Static and Dynamic Type

  • Static and Dynamic Type
  • Changes to Scope in 61B

Using Inheritance Safely

67 of 68

Interface vs. Implementation Inheritance

Interface Inheritance (a.k.a. what):

  • Allows you to generalize code in a powerful, simple way.

Implementation Inheritance (a.k.a. how):

  • Allows code-reuse: Subclasses can rely on superclasses or interfaces.
    • Example: print() implemented in List61B.java.
    • Gives another dimension of control to subclass designers: Can decide whether or not to override default implementations.

Important: In both cases, we specify “is-a” relationships, not “has-a”.

  • Good: Dog implements Animal, SLList implements List61B.
  • Bad: Cat implements Claw, Set implements SLList.

68 of 68

The Dangers of Implementation Inheritance

Particular Dangers of Implementation Inheritance

  • Makes it harder to keep track of where something was actually implemented (though a good IDE makes this better).
  • Rules for resolving conflicts can be arcane. Won’t cover in 61B.
    • Example: What if two interfaces both give conflicting default methods?
  • Encourages overly complex code (especially with novices).
    • Common mistake: Has-a vs. Is-a!
  • Breaks encapsulation!
    • What is encapsulation? See next week.