// This code requires Intermediate Java and the prof2.plt // (or later) patch class Posn { double x; double y; Posn(double x, double y) { this.x = x; this.y = y; } public boolean equals(Object o) { // See the slides for the improvement // using Advanced Java's instanceof return (this.x == ((Posn)o).x) && (this.y == ((Posn)o).y); } } abstract class List { abstract boolean isMember(Object o); abstract Object nth(int n); } class Empty extends List { Empty() { } boolean isMember(Object o) { return false; } Object nth(int n) { return new Empty(); } } class Cons extends List { Object first; List rest; Cons(Object first, List rest) { this.first = first; this.rest = rest; } boolean isMember(Object o) { return this.first.equals(o) || this.rest.isMember(o); } Object nth(int n) { if (n == 0) return this.first; else return this.rest.nth(n-1); } } // ---------------------------------------- interface NamedPlace { boolean isNice(); } abstract class Door { abstract List places(); } class Escape extends Door implements NamedPlace { String name; Escape(String name) { this.name = name; } List places() { return new Cons(this, new Empty()); } boolean isNice() { return !this.name.equals("mars"); } } class Into extends Door { Room next; Into(Room next) { this.next = next; } List places() { return this.next.places(); } } class NamedInto extends Into implements NamedPlace { String name; NamedInto(Room next, String name) { super(next); this.name = name; } List places() { return new Cons(this, super.places()); } boolean isNice() { return true; } } class Short extends Into { double height; Short(Room next, double height) { super(next); this.height = height; } } class Room { Door left; Door right; Room(Door left, Door right) { this.left = left; this.right = right; } List places() { List l = this.left.places(); List r = this.right.places(); return l.append(r); } } class Person { String dest; double height; Person(String dest, double height) { this.dest = dest; this.height = height; } boolean isDest(String s) { return this.dest.equals(s); } } // The Factory class helps in writing tests: // new Factory().Example().escapePath(new Person("mars", 1)) class Factory { Factory() { } Room Example() { Door meadow = new Escape("meadow"); Door street = new Escape("street"); Room ms = new Room(meadow, street); Room planets = new Room(new Escape("mars"), new Escape("venus")); return new Room(new NamedInto(ms, "crossing"), new Short(planets, 1)); } } // ---------------------------------------- abstract class List { abstract boolean isMember(Object o); abstract List append(List l); } class Empty extends List { Empty() { } boolean isMember(Object o) { return false; } List append(List l) { return l; } } class Cons extends List { Object first; List rest; Cons(Object first, List rest) { this.first = first; this.rest = rest; } boolean isMember(Object o) { return this.first.equals(o) || this.rest.isMember(o); } List append(List l) { return new Cons(this.first, this.rest.append(l)); } }