|
 |
|
Midterm exam 2 review
|
|
|
 |
|
Inheritance
|
|
|
 |
|
big idea 1: code reuse
|
|
|
 |
|
two types: “class” vs. “interface” inheritance
|
|
|
 |
|
syntactically: “extends” vs. “implements”
|
|
|
 |
|
subclassing a class gets us behavior “for free” (big idea 1)
|
|
|
 |
|
implementing an interface gives us a consistent API for users of our class
|
|
|
 |
|
API = Application Programming Interface
|
|
|
 |
|
third type: “abstract class”
|
|
|
 |
|
part behavior, part API (methods that have no bodies are declared “abstract”)
|
|
|
 |
|
big idea 2: polymorphism
|
|
|
 |
|
being able to treat instances of a subclass of C as though they were instances of C itself
|
|
|
 |
|
e.g., a polymorphic method that takes an Object can be passed an instance of any object (e.g., a Monster), because a Monster “is-a” Object
|
|
|
 |
|
e.g., a polymorphic array of Objects can hold instances of a mixture of different types (e.g., Monsters, Dates, Strings), because each slot can hold an instance of any subclass of Object
|
|
|
 |
|
important syntax: “super”
|
|
|
 |
|
allows us to access methods/attributes of the superclass
|
|
|
 |
|
remember: if we define methods in a subclass that already exist in a superclass, these methods are overridden — “super” lets us call the original superclass versions
|
|
|
 |
|
List Abstract Data Type (ADT)
|
|
|
 |
|
Specified using an interface
|
|
|
 |
|
Operations: add (to end), insert (at some position), remove (by position), remove (using a Predicate), getCount, sort (using a Comparator)
|
|
|
 |
|
Two implementations: ExpandingArray vs. Linked
|
|
|
 |
|
different “backing stores”: array of objects vs. individual node per datum
|
|
|
 |
|
expanding array required shifting elements and allocating new arrays and copying original items over
|
|
|
 |
|
linked implementation required allocating a new node for each datum inserted
|
|
|
 |
|
also required tracking head & tail nodes
|
|
|
 |
|
Know how to complete / implement methods of the two list implementations!
|
|
|
 |
|
Performance characteristics
|
|
|
 |
|
Expanding array:
|
|
|
 |
|
when it fills up we have to “expand” by allocating & copying (expensive)
|
|
|
 |
|
inserting / removing from the beginning or middle requires a lot of element shifting (expensive)
|
|
|
 |
|
Linked:
|
|
|
 |
|
much more uniform/consistent performance — does not require shifting or moving elements when inserting or removing
|
|
|
 |
|
at expense of having to constantly allocate nodes
|
|
|
 |
|
Generics
|
|
|
 |
|
provides type parameterization
|
|
|
 |
|
e.g., List<Monster> monsters;
|
|
|
 |
|
e.g., class LinkedList<T> extends List<T>
|
|
|
 |
|
e.g., T get(int index) { … }
|
|
|
 |
|
why generics? (especially given that we have polymorphism)
|
|
|
 |
|
sometimes it’s very useful to be able to restrict the scope of polymorphism
|
|
|
 |
|
e.g., we don’t always want to be able to put any sort of object in a a list
|
|
|
 |
|
which would be required if the “add” method took an object type (e.g., void add (Object o)
|
|
|
 |
|
e.g., void add (T o), setting T to Monster, restricts the list to containing only Monsters (and instances of subclasses of Monster)
|
|
|
 |
|
Predicates & Comparators
|
|
|
|
|
|
public interface Predicate<T> { public boolean evaluate(T obj); }
public interface Comparator<T> { public int compare(T o1, T o2); }
|
|
|
 |
|
both Interfaces that are used for evaluating arbitrary objects, usually within the context of a data structure (such as a list)
|
|
|
 |
|
Know how to use them!
|
|
|
 |
|
Anonymous class
|
|
|
 |
|
a class without a name — have to instantiate immediately (i.e., upon definition)
|
|
|
 |
|
almost always a subclass of an existing class/interface
|
|
|
 |
|
very useful for when we don’t want to create a separate file for a class definition — e.g., in scenarios where we need to create “throwaway”, customized objects
|
|
|
 |
|
e.g., for creating a custom Predicate
|
|
|
|
|
|
// following creates an anonymous subclass of Predicate, // defining the “evaluate” method, then instantiates it Predicate<Monster> pred = new Predicate<Monster>(){ public boolean evaluate(Monster m){ return m.getName().equals(“Vampire”); } };
|
|
|