CS61B, 2022
Lecture 8: Interface and Implementation Inheritance
AList and SLList
After adding the insert methods from discussion 3, our AList and SLList classes 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()
}
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.
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);
}
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);
}
Method Overloading in Java
Java allows multiple methods with same name, but different parameters.
public static String longest(AList<String> list) {
...
}
public static String longest(SLList<String> list) {
...
}
The Downsides
While overloading works, it is a bad idea in the case of longest. Why?
Hypernyms, Hyponyms, and Interface Inheritance
Hypernyms
In natural languages (English, Spanish, Chinese, Tagalog, etc.), we have a concept known as a “hypernym” to deal with this problem.
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.
Hypernym and Hyponym
We use the word hyponym for the opposite type of relationship.
Hypernyms and hyponyms comprise a hierarchy.
(for fun: see the WordNet project)
animal
omnivore
herbivore
carnivore
feline
canine
dog
Simple Hyponymic Relationships in Java
SLLists and ALists are both clearly some kind of “list”.
Expressing this in Java is a two-step process:
List61B
SLList
AList
Step 1: Defining a List61B
We’ll use the new keyword interface instead of class to define a List61B.
Step 1: Defining a List61B
We’ll use the new keyword interface instead of class to define a List61B.
public interface List61B<Item> {
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 void insert(Item x, int position);
public int size();
}
List61B
Step 2: Implementing the List61B Interface
We’ll now:
public class AList<Item> implements List61B<Item>{
...
public void addLast(Item x) {
...
List61B
SLList
AList
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);
Overriding vs. Overloading
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)
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.
public class Dog implements Animal {
public void makeNoise(Dog x) {
...
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
Optional Step 2B: Adding the @Override Annotation
In 61b, we’ll always mark every overriding method with the @Override annotation.
public class AList<Item> implements List61B<Item>{
...
@Override
public void addLast(Item x) {
...
List61B
SLList
AList
Method Overriding
If a subclass has a method with the exact same signature as in the superclass, we say the subclass overrides the method.
Why use @Override?
Interface Inheritance
Interface Inheritance
Specifying the capabilities of a subclass using the implements keyword is known as interface inheritance.
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!
Interface Inheritance
Specifying the capabilities of a subclass using the implements keyword is known as interface inheritance.
Interface inheritance is a powerful tool for generalizing code.
Collection61B
List61B
SLList
AList
Copying the Bits
Two seemingly contradictory facts:
public static String longest(List61B<String> list) {
int maxDex = 0;
for (int i = 0; i < list.size(); i += 1)
...
public static void main(String[] args) {
AList<String> a1 = new AList<String>();
a1.addLast("horse");
WordUtils.longest(a1);
}
How can we copy the bits in a1 to list?
Copying the Bits
Answer: If X is a superclass of Y, then memory boxes for X may contain Y.
public static String longest(List61B<String> list) {
int maxDex = 0;
for (int i = 0; i < list.size(); i += 1)
...
public static void main(String[] args) {
AList<String> a1 = new AList<String>();
a1.addLast("horse");
WordUtils.longest(a1);
}
How can we copy the bits in a1 to list?
Question: https://www.yellkey.com/quite
Will the code below compile? If so, what happens when it runs?
public static void main(String[] args) {
List61B<String> someList = new SLList<String>();
someList.addFirst("elk");
}
Question
Will the code below compile? If so, what happens when it runs?
public static void main(String[] args) {
List61B<String> someList = new SLList<String>();
someList.addFirst("elk");
}
Implementation Inheritance: Default Methods
Implementation Inheritance
Interface inheritance:
For better or worse, Java also allows implementation inheritance.
Use the default keyword to specify a method that subclasses should inherit from an interface.
Default Method Example: print()
public interface List61B<Item> {
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 void insert(Item x, int position);
public int size();
default public void print() {
for (int i = 0; i < size(); i += 1) {
System.out.print(get(i) + " ");
}
System.out.println();
}
}
Question: https://www.yellkey.com/catch
Is the print() method efficient?
public interface List61B<Item> {
...
default public void print() {
for (int i = 0; i < size(); i += 1) {
System.out.print(get(i) + " ");
}
System.out.println();
}
}
Question
Is the print() method efficient?
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 SLists.
Overriding Default Methods
If you don’t like a default method, you can override it.
public interface SLList<Item> implements {
@Override
public void print() {
for (Node p = sentinel.next; p != null; p = p.next) {
System.out.print(p.item + " ");
}
System.out.println();
}
}
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?
public static void main(String[] args) {
List61B<String> someList = new SLList<String>();
someList.addLast("elk");
someList.addLast("are");
someList.addLast("watching");
someList.print();
}
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?
public static void main(String[] args) {
List61B<String> someList = new SLList<String>();
someList.addLast("elk");
someList.addLast("are");
someList.addLast("watching");
someList.print();
}
Static and Dynamic Type, Dynamic Method Selection
Static Type vs. Dynamic Type
Every variable in Java has a “compile-time type”, a.k.a. “static type”.
�Variables also have a “run-time type”, a.k.a. “dynamic type”.
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.
Static Type vs. Dynamic Type
Every variable in Java has a “compile-time type”, a.k.a. “static type”.
�Variables also have a “run-time type”, a.k.a. “dynamic type”.
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.
Static Type vs. Dynamic Type
Every variable in Java has a “compile-time type”, a.k.a. “static type”.
�Variables also have a “run-time type”, a.k.a. “dynamic type”.
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
Animal
Fox
lt1
a1
LivingThing
Animal
Technically requires a “cast”. See next lecture.
Static Type vs. Dynamic Type
Every variable in Java has a “compile-time type”, a.k.a. “static type”.
�Variables also have a “run-time type”, a.k.a. “dynamic type”.
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
Static Type vs. Dynamic Type
Every variable in Java has a “compile-time type”, a.k.a. “static type”.
�Variables also have a “run-time type”, a.k.a. “dynamic type”.
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
Dynamic Method Selection For Overridden Methods
Suppose we call a method of an object using a variable with:
�Then if Y overrides the method, Y’s method is used instead.
public static void main(String[] args) {
List61B<String> s1= new SLList<String>();
someList.addLast("elk");
someList.addLast("are");
someList.addLast("watching");
someList.print();
}
This term is a bit obscure.
List61B
List61B
SLList
Static Type
Dynamic Type
Note on Changes to DMS Scope in 61B
Older Versions of 61B
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.
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.
DMS Corner Case:
Signature Selection and
Dynamic Method Selection (Bonus Content)
Not covered on Exams
Dynamic Method Selection Puzzle: Try to Predict the Results
public interface Animal {
default void greet(Animal a) {
print("hello animal"); }
default void sniff(Animal a) {
print("sniff animal"); }
default void praise(Animal a) {
print("u r cool animal"); }
}
public class Dog implements Animal {
@Override� void sniff(Animal a) {
print("dog sniff animal"); }
void praise(Dog a) {
print("u r cool dog"); }
}
Animal a = new Dog();
Dog d = new Dog();
a.greet(d);
a.sniff(d);
d.praise(d);
a.praise(d);
Before we start, let’s explicitly show the methods that are inherited by the Dog class.
Dynamic Method Selection Puzzle: Try to Predict the Results
public interface Animal {
default void greet(Animal a) {
print("hello animal"); }
default void sniff(Animal a) {
print("sniff animal"); }
default void praise(Animal a) {
print("u r cool animal"); }
}
public class Dog implements Animal {
default void greet(Animal a)
@Override� void sniff(Animal a) {
print("dog sniff animal"); }
default void praise(Animal a)
void praise(Dog a) {
print("u r cool dog"); }
}
Animal a = new Dog();
Dog d = new Dog();
a.greet(d);
a.sniff(d);
d.praise(d);
a.praise(d);
Note: default methods in the Dog class is shown grayed out to indicate they are inherited.
Dynamic Method Selection Puzzle: Try to Predict the Results
public interface Animal {
default void greet(Animal a) {
print("hello animal"); }
default void sniff(Animal a) {
print("sniff animal"); }
default void praise(Animal a) {
print("u r cool animal"); }
}
public class Dog implements Animal {
default void greet(Animal a)
@Override� void sniff(Animal a) {
print("dog sniff animal"); }
default void praise(Animal a)
void praise(Dog a) {
print("u r cool dog"); }
}
Animal a = new Dog();
Dog d = new Dog();
a.greet(d); // "hello animal"
a.sniff(d);
d.praise(d);
a.praise(d);
Note: default methods in the Dog class is shown grayed out to indicate they are inherited.
Dynamic Method Selection Puzzle: Try to Predict the Results
public interface Animal {
default void greet(Animal a) {
print("hello animal"); }
default void sniff(Animal a) {
print("sniff animal"); }
default void praise(Animal a) {
print("u r cool animal"); }
}
public class Dog implements Animal {
default void greet(Animal a)
@Override� void sniff(Animal a) {
print("dog sniff animal"); }
default void praise(Animal a)
void praise(Dog a) {
print("u r cool dog"); }
}
Animal a = new Dog();
Dog d = new Dog();
a.greet(d); // "hello animal"
a.sniff(d); // "dog sniff animal"
d.praise(d);
a.praise(d);
Note: default methods in the Dog class is shown grayed out to indicate they are inherited.
Dynamic Method Selection Puzzle: Try to Predict the Results
public interface Animal {
default void greet(Animal a) {
print("hello animal"); }
default void sniff(Animal a) {
print("sniff animal"); }
default void praise(Animal a) {
print("u r cool animal"); }
}
public class Dog implements Animal {
default void greet(Animal a)
@Override� void sniff(Animal a) {
print("dog sniff animal"); }
default void praise(Animal a)
void praise(Dog a) {
print("u r cool dog"); }
}
Animal a = new Dog();
Dog d = new Dog();
a.greet(d); // "hello animal"
a.sniff(d); // "dog sniff animal"
d.praise(d); // "u r cool dog"
a.praise(d);
Note: default methods in the Dog class is shown grayed out to indicate they are inherited.
Dynamic Method Selection Puzzle: Try to Predict the Results
public interface Animal {
default void greet(Animal a) {
print("hello animal"); }
default void sniff(Animal a) {
print("sniff animal"); }
default void praise(Animal a) {
print("u r cool animal"); }
}
public class Dog implements Animal {
default void greet(Animal a)
@Override� void sniff(Animal a) {
print("dog sniff animal"); }
default void praise(Animal a)
void praise(Dog a) {
print("u r cool dog"); }
}
Animal a = new Dog();
Dog d = new Dog();
a.greet(d); // "hello animal"
a.sniff(d); // "dog sniff animal"
d.praise(d); // "u r cool dog"
a.praise(d); // “u r cool animal”
Why?
praise is overloaded, not overridden!
An Alternate Viewpoint: DMS as a Two Step Process
Another way to think about dynamic method selection is as a 2 step process, where step 1 happens at compile time, and step 2 happens at runtime.
These two steps obey rules that are easy to apply, but take time to understand.
An Alternate Viewpoint: DMS as a Two Step Process
Another way to think about dynamic method selection is as a 2 step process, where step 1 happens at compile time, and step 2 happens at runtime.
These two steps obey rules that are easy to apply, but take time to understand.
Let’s do an exercise to understand this first rule.
Dynamic Method Selection Puzzle
What method signature will be used for each call?
public interface Animal {
default void greet(Animal a)
default void sniff(Animal a)
default void praise(Animal a) {
}
public class Dog implements Animal {
default void greet(Animal a)
void sniff(Animal a)
default void praise(Animal a)
void praise(Dog a)
}
Animal a = new Dog();
Dog d = new Dog();
a.greet(d);
a.sniff(d);
d.praise(d);
a.praise(d);
Dynamic Method Selection Puzzle
What method signature will be used for each call?
public interface Animal {
default void greet(Animal a)
default void sniff(Animal a)
default void praise(Animal a) {
}
public class Dog implements Animal {
default void greet(Animal a)
void sniff(Animal a)
default void praise(Animal a)
void praise(Dog a)
}
Animal a = new Dog();
Dog d = new Dog();
a.greet(d); // greet(Animal a)
a.sniff(d);
d.praise(d);
a.praise(d);
Dynamic Method Selection Puzzle
What method signature will be used for each call?
public interface Animal {
default void greet(Animal a)
default void sniff(Animal a)
default void praise(Animal a) {
}
public class Dog implements Animal {
default void greet(Animal a)
void sniff(Animal a)
default void praise(Animal a)
void praise(Dog a)
}
Animal a = new Dog();
Dog d = new Dog();
a.greet(d); // greet(Animal a)
a.sniff(d); // sniff(Animal a)
d.praise(d);
a.praise(d);
Note there are TWO sniff(Animal) methods.
Paul Hilfinger calls these a “Dynamic Method Set”.
Dynamic Method Selection Puzzle
What method signature will be used for each call?
public interface Animal {
default void greet(Animal a)
default void sniff(Animal a)
default void praise(Animal a) {
}
public class Dog implements Animal {
default void greet(Animal a)
void sniff(Animal a)
default void praise(Animal a)
void praise(Dog a)
}
Animal a = new Dog();
Dog d = new Dog();
a.greet(d); // greet(Animal a)
a.sniff(d); // sniff(Animal a)
d.praise(d); // praise(Dog a)
a.praise(d);
Dynamic Method Selection Puzzle
What method signature will be used for each call?
public interface Animal {
default void greet(Animal a)
default void sniff(Animal a)
default void praise(Animal a) {
}
public class Dog implements Animal {
default void greet(Animal a)
void sniff(Animal a)
default void praise(Animal a)
void praise(Dog a)
}
Animal a = new Dog();
Dog d = new Dog();
a.greet(d); // greet(Animal a)
a.sniff(d); // sniff(Animal a)
d.praise(d); // praise(Dog a)
a.praise(d); // praise(Animal a)
An Alternate Viewpoint: DMS as a Two Step Process
Another way to think about dynamic method selection is as a 2 step process, where step 1 happens at compile time, and step 2 happens at runtime.
These two steps obey rules that are easy to apply, but take time to understand.
In the previous exercise, we saw how to apply rule 1.
Dynamic Method Selection Puzzle: Try to Predict the Results
public interface Animal {
default void greet(Animal a) {
print("hello animal"); }
default void sniff(Animal a) {
print("sniff animal"); }
default void praise(Animal a) {
print("u r cool animal"); }
}
public class Dog implements Animal {
default void greet(Animal a)
@Override� void sniff(Animal a) {
print("dog sniff animal"); }
default void praise(Animal a)
void praise(Dog a) {
print("u r cool dog"); }
}
Animal a = new Dog();
Dog d = new Dog();
a.greet(d); // greet(Animal a)
a.sniff(d); // sniff(Animal a)
d.praise(d);// praise(Dog a)
a.praise(d);// praise(Animal a)
Results of rule 1 shown in figure to the right as comments
Dynamic Method Selection Puzzle: Try to Predict the Results
public interface Animal {
default void greet(Animal a) {
print("hello animal"); }
default void sniff(Animal a) {
print("sniff animal"); }
default void praise(Animal a) {
print("u r cool animal"); }
}
public class Dog implements Animal {
default void greet(Animal a)
@Override� void sniff(Animal a) {
print("dog sniff animal"); }
default void praise(Animal a)
void praise(Dog a) {
print("u r cool dog"); }
}
Animal a = new Dog();
Dog d = new Dog();
a.greet(d); // greet(Animal a) - “hello animal”
a.sniff(d); // sniff(Animal a)
d.praise(d);// praise(Dog a)
a.praise(d);// praise(Animal a)
Invoking object is a.
Dynamic type of a is Dog
Dynamic Method Selection Puzzle: Try to Predict the Results
public interface Animal {
default void greet(Animal a) {
print("hello animal"); }
default void sniff(Animal a) {
print("sniff animal"); }
default void praise(Animal a) {
print("u r cool animal"); }
}
public class Dog implements Animal {
default void greet(Animal a)
@Override� void sniff(Animal a) {
print("dog sniff animal"); }
default void praise(Animal a)
void praise(Dog a) {
print("u r cool dog"); }
}
Animal a = new Dog();
Dog d = new Dog();
a.greet(d); // greet(Animal a) - “hello animal”
a.sniff(d); // sniff(Animal a) - “dog sniff animal”
d.praise(d);// praise(Dog a)
a.praise(d);// praise(Animal a)
Invoking object is a.
Dynamic type of a is Dog
Dynamic Method Selection Puzzle: Try to Predict the Results
public interface Animal {
default void greet(Animal a) {
print("hello animal"); }
default void sniff(Animal a) {
print("sniff animal"); }
default void praise(Animal a) {
print("u r cool animal"); }
}
public class Dog implements Animal {
default void greet(Animal a)
@Override� void sniff(Animal a) {
print("dog sniff animal"); }
default void praise(Animal a)
void praise(Dog a) {
print("u r cool dog"); }
}
Animal a = new Dog();
Dog d = new Dog();
a.greet(d); // greet(Animal a) - “hello animal”
a.sniff(d); // sniff(Animal a) - “dog sniff animal”
d.praise(d);// praise(Dog a) - “u r cool dog”
a.praise(d);// praise(Animal a)
Invoking object is d.
Dynamic type of d is Dog
Dynamic Method Selection Puzzle: Try to Predict the Results
public interface Animal {
default void greet(Animal a) {
print("hello animal"); }
default void sniff(Animal a) {
print("sniff animal"); }
default void praise(Animal a) {
print("u r cool animal"); }
}
public class Dog implements Animal {
default void greet(Animal a)
@Override� void sniff(Animal a) {
print("dog sniff animal"); }
default void praise(Animal a)
void praise(Dog a) {
print("u r cool dog"); }
}
Animal a = new Dog();
Dog d = new Dog();
a.greet(d); // greet(Animal a) - “hello animal”
a.sniff(d); // sniff(Animal a) - “dog sniff animal”
d.praise(d);// praise(Dog a) - “u r cool dog”
a.praise(d);// praise(Animal a) - “u r cool animal”
Invoking object is a.
Dynamic type of a is Dog
Practical Inheritance
Lists
In lecture, we’ve built two types of lists: ALists and SLLists.
List61B<Integer> L = new AList<>();
L.addLast(5);
L.addLast(10);
L.addLast(15);
L.print();
L = []
L.append(3)
L.append(4)
L.append(5)
print(L)
$ java ListExample
3 4 5
$ python list_example.py
[3 4 5]
Lists in Real Java Code
We built a list from scratch, but Java provides a built-in List interface and several implementations, e.g. ArrayList.
java.util.List<Integer> L = new java.util.ArrayList<>();
L.add(5);
L.add(10);
L.add(15);
System.out.println(L);
List61B<Integer> L = new AList<>();
L.addLast(5);
L.addLast(10);
L.addLast(15);
L.print();
For the rest of 61B, we encourage you to use Java’s built in List interface and ArrayList class!
List methods here.
Lists in Real Java Code
By including “import java.util.List” and “import java.util.ArrayList” at the top of the file, we can make our code more compact.
import java.util.List;
import java.util.ArrayList;
public class SimpleBuiltInListExample {
public static void main(String[] args) {
List<Integer> L = new ArrayList<>();
L.add(5); L.add(10); L.add(15);
System.out.println(L);
List<Integer> L2 = Utils.readIntsFromFile(“somedata.csv”);
}
}
If we import, we can use the “simple name” (ArrayList) as opposed to the longer “canonical name” (java.util.ArrayList).
Interface vs. Implementation Inheritance
Interface vs. Implementation Inheritance
Interface Inheritance (a.k.a. what):
Implementation Inheritance (a.k.a. how):
Important: In both cases, we specify “is-a” relationships, not “has-a”.
The Dangers of Implementation Inheritance
Particular Dangers of Implementation Inheritance
Reflections on Course and
AMA 1
Reassurances Regarding 61B This Semester
Tilt was really hard for students with less experience!
One major mistake on our part: Not properly taking into account Labor Day. I’m calling this out so you don’t feel like you did something wrong.
Unrelated issue: Proj 1a was not supposed to have .equals.
Pacing
Exam Studying Tips
How to Study for an Exam:
One Last Note on Plagiarism
Collaboration Policy
We have enumerated very specific rules whose violation will result in being reported to the office of student conduct:
Permissible But with Extreme Caution
Were it enforceable, I’d say no looking at other students’ code at all, but I want you to take these rules seriously (unlike, say, speed limits).
Plagiarism will (Probably) be Detected, and Dealt with Harshly
Plagiarism detection software is very sophisticated.
Every semester we send 50-100 cases to the Office of Student Conduct.
Please contact us if 61B is causing massive disruptions to your life. We are willing to give more slip days and can be flexible to accommodate you.
AMA (Time Permitting)