Lecture 39: Drills
1 Definitions
interface
class
object
abstract class
iterator
comparator
anonymous inner class
lambda expression
visitor
2 Concepts
Describe two ways in which an abstract class and a class differ.
a class implements an interface
a class extends a class
an interface extends an interface
3 Hash code
If two objects have the same hash code, what can you conclude about the equality of those objects (assuming their equals and hashCode methods are correct)?
4 Comparisons
What’s the difference between a comparator and comparable object?
5 Abstract classes
Describe a situation in which writing an abstract class is justified.
6 Types
Is this program well-typed?
Listof<Integer> is = new Cons <>(5, new Empty<>()); |
System.out.println(is.first); |
Is this program well-typed?
Pairof<Integer, Boolean> p = null; |
System.out.println(p.left); |
7 Tree traversals
Suppose you had a binary search tree and you want to produce a list of elements in the tree in sorted order. Which traversal do you want?
NLR
LNR
LRN
8 Computing with iteration
Implement the following method:
// Compute the average of all the numbers in it. |
// Assume: it has at least one number |
Double avg(Iterable<Double> it) { ... } |
9 Lambda expressions
Rewrite the following to use lambda expression notation:
Function<Double,Double> dbl = new Function<>() { |
public Double apply(Double d) { |
return d * d; |
} |
}; |
10 Methods for lists
Assume the following interface exists:
// Functions X -> Optional<Y> |
interface OptFun<X, Y> extends Function<X, Optional<Y>> {} |
Design the following methods for Listof<X>:
// Produce the list of elements in this list which satisfy p |
Listof<X> filter(Predicate<X> p); |
|
// Produce the list of results for which f produces something in this list |
<R> Listof<R> filterMap(OptFun<X,R> f); |
|
// Produce the first element in this list for which p produces true |
Optional<X> findPred(Predicate<X> p); |
Show that you can define filter in terms of filterMap:
abstract class AListof<X> implements Listof<X> { |
// Produce the list of elements in this list which satisfy p |
public Listof<X> filter(Predicate<X> p) { |
... |
} |
} |
11 Double dispatch
When is it justified to use the double dispatch pattern?
Assume the following definitions:
interface BT<X> { |
// Produce the tree obtained by following p in this tree |
BT<X> follow(BTPath p); |
} |
|
class Leaf<X> implements BT<X> { ...usual defn...} |
|
class Node<X> implements BT<X> { ...usual defn...} |
|
// Interp: a path through a binary tree |
interface BTPath {} |
|
// Interp: end of a path |
class End implements BTPath {} |
|
// Interp: go left, followed by path rest |
class Left implements BTPath { |
BTPath rest; |
Left(BTPath rest) { |
this.rest = rest; |
} |
} |
|
// Interp: go right, followed by path rest |
class Right implements BTPath { |
BTPath rest; |
Right(BTPath rest) { |
this.rest = rest; |
} |
} |
Using the double dispatch pattern, design the follow method. You may raise an exception if following a path leads you off the end of a binary tree.
12 Graphs
Here is a representation for directed graphs:
// A node in a directed graph |
class GNode { |
String name; |
Listof<GNode> neighbors; |
|
GNode(String name) { |
this.name = name; |
this.neighbors = new Empty<>(); |
} |
|
// EFFECT: add the given node to this node's neighbor |
public void addNeighbor(GNode n) { |
this.neighbors = new Cons<>(n, this.neighbors); |
} |
|
// Is there a path from this node to the given node? |
public Boolean hasPath(GNode to) { ... } |
} |
Design the hasPath method. Here some examples:
void testGraph(Tester t) { |
// +---------+ |
// v | |
// A--->B--->C-->D |
// +--->E-->F |
// |
GNode a = new GNode("A"); |
GNode b = new GNode("B"); |
GNode c = new GNode("C"); |
GNode d = new GNode("D"); |
GNode e = new GNode("E"); |
GNode f = new GNode("F"); |
|
a.addNeighbor(b); |
b.addNeighbor(c); |
c.addNeighbor(d); |
b.addNeighbor(e); |
e.addNeighbor(f); |
c.addNeighbor(a); |
|
t.checkExpect(a.hasPath(a), true); |
t.checkExpect(a.hasPath(b), true); |
t.checkExpect(a.hasPath(e), true); |
t.checkExpect(e.hasPath(d), false); |
} |
13 Visitors
Recall the following method for Listof<X>:
// Is this list sorted in ascending order according to c? |
Boolean isSorted(Comparator<X> c); |
It can be implemented with an accumulator helper method that remembers the prior element in the list.
Suppose this method was not available for Listof<X> and you couldn’t make any further changes to Listof<X>. Design a visitor that computes the same thing as this method.