next up previous
Next: 1.5.1 Member Hoisting Up: 1. From Scheme to Previous: 1.4.4 Printing Objects

  
1.5 The Union and Composite Patterns

In our department directory example, an object of type Entry only has one form, namely an instance of class Entry. If we were designing the data for a more comprehensive directory such as a city phone directory, we would need more than one form of entry. At a minimum, we would need separate entry formats for business listings, government listings, and residential listings. For such a phone directory, we might define an entry as follows.

A CityEntry is either:

where name is a string specifying the name for the listing, addr is a string specifying the street address and ZIP code for the listing, phone is a string specifying the phone number (with area code) for the listing, city and state are strings specifying the city and state for the listing, and gov is a string specifying the government entity for that the listing, e.g. the "City of Houston".

The BusinessEntry and GovernmentEntry forms include city and state information because businesses and government agencies that serve clients in cities outside their local calling area often elect to have their phone numbers included in the directories of other cities (in addition to the cities where they are located). The government listings include a string specifying the government entity to which they belong. For example, a listing for the federal Department of Transportation, would specify the "U.S. Government" as the gov field.

In Scheme, we would represent such an entry data type by defining three different structures:

;; a CityEntry is either:
;;   a BusinessEntry 
;;     (make-BusinessEntry name addr phone city state), 
;;   or a GovernmentEntry 
;;     (make-BusinessEntry name addr phone city state gov),
;;   or a ResidentialEntry 
;;     (make-ResidentialEntry name addr phone).

(define-struct BusinessEntry (name addr phone city state))
(define-struct GovernmentEntry (name addr phone city state gov))
(define-struct ResidentialEntry (name addr phone))
Note that the type CityEntry consisting of the union of the types BusinessEntry, GovernmentEntry, and ResidentialEntry is not defined in program text because all union types in Scheme are implicit.

In Java, we can define the CityEntry type by introducing a ``dummy'' CityEntry class that we extend by ``concrete'' classes for each different form of Entry data. This technique, which is widely used in object-oriented programming, is called the union pattern. In this pattern, each different concrete class extending the root abstract class is called a variant. The following Java code defines the city-entry type:

abstract class CityEntry {
}

class BusinessEntry extends Entry {

  String name;	
  String address;
  String phone;
  String city;
  String state;

  /* constructor */
  BusinessEntry(String a, String p, String c, String s) {
    this.address = a;
    this.phone = p;
    this.city = c;
    this.state = s;
  }

  /* accessors */
  String getAddress() { return this.address; }
  String getPhone() { return this.phone; }
  String getCity() { return this.city; }
  String getState() { return this.state; }	
}

class GovernmentEntry extends Entry {


  String name;	
  String address;
  String phone;
  String city;
  String state;
  String government;

  /* constructor */
  GovernmentEntry(String n, String a, String p, String c, String s, String g) {
    this.name = n;
    this.address = a;
    this.phone = p;
    this.city = c;
    this.state = s;
    this.government = g;
  }

  /* accessors */
  String getName() { return this.name; }
  String getAddress() { return this.address; }
  String getPhone() { return this.phone; }
  String getCity() { return this.city; }
  String getState() { return this.state; }	
}

class ResidentialEntry extends Entry

  String name;	
  String address;
  String phone;

  /* constructor */
  ResidentialEntry(String n, String a, String p) {
    this.name = n;
    this.address = a;
    this.phone = p;
  }

  /* accessors */
  String getName() { return this.name; }	
  String getAddress() { return this.address; }
  String getPhone() { return this.phone; }
}

Note that each concrete class includes exactly the same fields as the corresponding Scheme structure definition. The pivotal differences between the Java code and the corresponding Scheme code are (i) the presence of the abstract class CityEntry in the Java Code identifying the union type which is left implicit in Scheme and (ii) the explicit definitions of constructors and accessors (selectors) in the Java concrete classes which are automatically generated by the Scheme structure definitions.

The Java code in the CityEntry example above involves several concepts that we have not discussed before.

The following expression creates a BusinessEntry for Rice University

new BusinessEntry("Rice University","6100 Main Street","713-527-8101","Houston", "Texas")
This syntax is wordy but straightforward. Don't forget to include the keyword new at the front on each constructor invocation!



 
next up previous
Next: 1.5.1 Member Hoisting Up: 1. From Scheme to Previous: 1.4.4 Printing Objects
Corky Cartwright
2000-01-07