Translating an algebraic specification into Java. Recipe for implementing an immutable ADT that is specified by an algebraic specification. Let T be the name of the ADT. Assumptions: Except for the basic creators, each operation of the ADT takes at least one argument of type T. Except for the basic creators, each operation is specified by one or more equations. If an operation is specified by more than one equation, then the left hand sides of the equations differ according to which basic creator was used to create an argument of type T. The equations have certain other technical properties that allow them to be used as rewriting rules. We are to implement the ADT in Java. The operations of the ADT are to be implemented as static methods of a class named T. Recipe: Determine which operations of the ADT are basic creators, and which are other operations. Define an abstract class named T. For each basic creator c of the ADT, define a concrete subclass of T. For each concrete subclass, declare instance variables with the same types and names as the arguments that are passed to the corresponding basic creator c. For each concrete subclass, define a Java constructor that takes the same arguments as the basic creator c and stores those arguments into the instance variables. [So far we have defined the representation of T. Now we have to define the operations.] For each operation f of the ADT that is not a basic creator, declare an abstract method f in the abstract class T. The explicit arguments of the abstract method f should be the same as the arguments of the operation f, except the abstract method f will take one less argument than f. That missing argument will be the receiver for calls to the abstract method f (so that argument will still be available to the abstract method f, as the value of Java's special variable this). That missing argument should be of type T. If the operation f has more than one argument of type T, so you have some choice as to which argument to omit, then you should omit the argument that discriminates between the various equations for f in the algebraic specification. For each operation of the ADT, define a static method within the abstract class. If the operation is a basic creator c, then the static method for c should create and return a new instance of the subclass that corresponds to c. If the operation is not a basic creator, then the static method for c should delegate to the corresponding abstract method for c, passing it all but one of its arguments. (The missing argument will be available to the abstract method via the special variable named "this".) Suppose, for example, that the static method T.f is called with arguments x1, x2, x3, and x4, where x1 is the only argument of type T. Then the body of T.f should be return x1.f (x2, x3, x4); For each concrete subclass C of T, define all of the abstract methods that were declared within the abstract base class for T. (These definitions define dynamic (as opposed to static) methods.) For each abstract method f that is defined within a subclass C, the body of f should return the value specified by the algebraic specification for the case in which Java's special variable this will be an instance of the class C. If the algebraic specification contains only one equation that describes the result of an operation f applied to an instance of C, and that equation has no side conditions, then the body of the dynamic method f should return the value expressed by the right hand side of that equation. If the algebraic specification contains more than one equation that describes the result of an operation f applied to an instance of C, then all of those equations should have side conditions. The body of the dynamic method f should test those side conditions to determine which equation is relevant. After it has determined which equation is relevant, it should return the value expressed by the right hand side of that equation If the algebraic specification does not contain any equations that describe the result of an operation f applied to an instance of C, then the body of the dynamic method f should throw a RuntimeException such as an IllegalArgumentException. Similarly, the body of the dynamic method f should throw a RuntimeException if there is no relevant equation (because the side conditions for all potentially relevant equations are false).