Assignment 6: Visitors
Goals: To practice using the visitor pattern
Instructions
As always, be very careful with your naming conventions. You should not use mutation on this assignment.
Due Date: Thursday October 26th at 9:00pm
Problem 1: Understanding Visitors
Getting started
Start a new project, and copy into it the following definitions of IList<T> and its supporting classes.
//represents a generic list interface IList<T> { } //represents an empty generic list class MtList<T> implements IList<T> { } //represents a generic non-empty list class ConsList<T> implements IList<T> { T first; IList<T> rest; ConsList(T first, IList<T> rest) { this.first = first; this.rest = rest; } }
6.1 Visitors for lists
In the following exercises, if you need to use any function objects, use the ones in Java’s functional interface.
Make sure to test the visitors that you design on lists of at least two different types.
Define an IListVisitor interface. How many type parameters will it need? (Hint: how many type parameters did the IShapeVisitor from class need, compared to how many type parameters IShape itself needed?) What methods will the visitor need? (Hint: what methods did the IShapeVisitor need, and how did that relate to the classes we had that implemented IShape?) Name all your methods visit(...) —
this is another example of overloading. Define a method ?????? accept(IListVisitor<??????> v) on IList<T>, and implement it on the classes implementing IList<T>. Fill in the question marks with whatever type parameter(s?) are needed.
Design a MapVisitor for lists. This visitor should behave like the map method that we designed in class.
Design a FoldRVisitor for lists that behaves like the foldr method we designed in class.
Design an AppendVisitor for lists that behaves like the append method we designed in class.
6.2 Visitors for ancestor trees
Copy the IAT interface and related classes from below into your project.
//represents an ancester tree interface IAT { } //represents an unknown ancestor tree class Unknown implements IAT { Unknown() { } } //represents a person in an ancester tree class Person implements IAT { String name; int yob; IAT parent1; IAT parent2; Person(String name, int yob, IAT parent1, IAT parent2) { this.name = name; this.yob = yob; this.parent1 = parent1; this.parent2 = parent2; } }
Design a visitor for IATs: define an IATVisitor interface. Name all your methods in IATVisitor visit(...) Add an accept method to IAT, and implement it for the relevant classes.
Design an IATVisitor called NamesVisitor that produces an IList<String> of the names of the people in an IAT. (Hint: you will probably want to use the AppendVisitor you designed earlier!)