/*
--- CSU213 Spring 2005 Lecture Notes ---------
Copyright 2005 Viera K. Proulx

Lecture 2: Happy Unions
*/

/* 
Goals:

 - learn to design classes that represent union of data types
 - understand that the concepts are the same

Let us return to the library catalog that contains information about books, 
CDs, and magazines. 

Books: title, author, catalog number, ... and more
CDs: title, artist, number of tracks, catalog number, ... and more
Magazines: title, volume or year, issue, catalog number, ... and more

Let us make examples of this kind of data:
  book: Cat in a Hat by Dr Seuss, number 77
  book: HtDP, by Matthias, number 42

  cd: Thriller, with Michael Jackson, 10 tracks, number 99
  cd: Pearl, by Janis Joplin, 12 tracks, number 88

  magazine: Time, issue 52 in 2004, number 33
  magazine: Wired, issue 3 in 2004, number 44


The data definition in HtDP would then be:

A Library item is one of 
 - (define-struct book (title author no))
   where title and author are Strings and no is a Number

 - (define-struct cd (title artist tracks no))
   where title and artist are Strings and tracks and no are Numbers

 - (define-struct mag (title year issue no))
   where title is a String and year, issue and no are Numbers

We have defined a class Book to represent the information about the books.
Similarly, we can design two other classes to represent the CDs and the 
magazines. The three class diagram would be:

  +---------------+    +---------------+    +--------------+  
  | Book          |    | CD            |    | Magazine     |  
  +---------------+    +---------------+    +--------------+  
  | String title  |    | String title  |    | String title |  
  | String author |    | String artist |    | int year     |  
  | int no        |    | int tracks    |    | int issue    |  
  +---------------+    | int no        |    | int no       |  
                       +---------------+    +--------------+  

and the definition of the Java classes follows immediately.

However, we would like to be able to express the relationship between these classes,
so that we can talk about library items as types of data.

To do this, we define a union of the three classes, represented by the following
diagram:

                         +----------+                         
                         | ALibItem |                         
                         +----------+                         
                         +----------+                         
                             / \                              
                             ---                              
                              |                               
          ------------------------------------------          
          |                    |                   |          
  +---------------+    +---------------+    +--------------+  
  | Book          |    | CD            |    | Magazine     |  
  +---------------+    +---------------+    +--------------+  
  | String title  |    | String title  |    | String title |  
  | String author |    | String artist |    | int year     |  
  | int no        |    | int tracks    |    | int issue    |  
  +---------------+    | int no        |    | int no       |  
                       +---------------+    +--------------+  
                                                              
  
The arrow connecting the three classes to the top one is a union arrow,
or 'inheritance' arrow. The class ALibItem is a super class, the three
classes below are its subclasses. We have examples of objects that 
belong to these three classes, but we cannot make examples of 
'ALibItem' - the class just defines a common type for its subclasses.
To make this clear, we have to define the class ALibItem as 'abstract'
class. It has no constructor - of course! The other three classes 
define their relationship to the super class by indicating that they
'extend' the super class:
*/


// to represent library items
abstract class ALibItem {
}

// to represent a book
class Book extends ALibItem {
  String title;
  String author;
  int no;

  Book(String title, String author, int no) {
    this.title = title;
    this.author = author;
    this.no = no;
  }
}

// to represent a CD
class CD extends ALibItem {
  String title;
  String artist;
  int tracks;
  int no;

  CD(String title, String artist, int tracks, int no) {
    this.title = title;
    this.artist = artist;
    this.tracks = tracks;
    this.no = no;
  }
}

// to represent a magazine
class Magazine extends ALibItem {
  String title;
  int year;
  int issue;
  int no;

  Magazine(String title, int year, int issue, int no) {
    this.title = title;
    this.year = year;
    this.issue = issue;
    this.no = no;
  }
}


/*
The examples of books then are defined as follows:

  Book ch = new Book("Cat in a Hat", "Dr Seuss", 77);
  Book htdp = new Book("HtDP", "Matthias F", 42);

  CD thriller = new CD("Thriller", "Michael Jackson", 10, 99);
  CD pearl = new CD("Pearl", "Janis Joplin", 12, 88);

  Magazine time = new Magazine("Time", 2004, 52, 33);
  Magazine wired = new Magazine("Wired", 2004, 3, 44);
*/

/*
Part 2: Common Data

We notice that every subclass of the class ALibItem contains 
a title and a catalog number. If we think about any other 
library items we may want to represent later, such as maps,
video tapes, DVDs, they will also have a title and a catalog number.
Because these fields are common to all subclasses, we can enforce
this by 'lifting' the fields to the abstract class. it will still
be an abstract class, as a title and a catalog number does not
provide all the information we need to know about a library 
item. the same book may be available as a book on tape, and 
in printed version, Sound of Music may be an audio CD, a DVD,
and a music score of the songs. However, by moving the field
definitions into a super class, we make sure that every class that
extends the abstract class ALibItem will contain at least these two 
fields. 

The new class definitions are:
*/

/*
                     +--------------+                     
                     | ALibItem     |                     
                     +--------------+                     
                     | String title |                     
                     | int no       |                     
                     +--------------+                     
                           / \                            
                           ---                            
                            |                             
          -----------------------------------------        
          |                    |                  |        
  +---------------+    +---------------+    +-----------+  
  | Book          |    | CD            |    | Magazine  |  
  +---------------+    +---------------+    +-----------+  
  | String author |    | String artist |    | int year  |  
  +---------------+    | int tracks    |    | int issue |  
                       +---------------+    +-----------+  
                                                          
                                                          

*/



// to represent a library item
abstract class ALibItem {
  String title;
  int no;
}

// to represent a book
class Book extends ALibItem {
  String author;

  Book(String title, int no, String author) {
    this.title = title;
    this.no = no;
    this.author = author;
  }
}

// to represent a CD
class CD extends ALibItem {
  String artist;
  int tracks;

  CD(String title, int no, String artist, int tracks) {
    this.title = title;
    this.no = no;
    this.artist = artist;
    this.tracks = tracks;
  }
}

// to represent a magazine
class Magazine extends ALibItem {
  int year;
  int issue;

  Magazine(String title, int no, int year, int issue) {
    this.title = title;
    this.no = no;
    this.year = year;
    this.issue = issue;
  }
}


/*
Notice that we had to change the order in which the fields appear in the
constructor. This is not a requirement in Java, but we will always do it.

The examples will have to be then modified as follows:


  Book ch = new Book("Cat in a Hat", 77, "Dr Seuss");
  Book htdp = new Book("HtDP", 42, "Matthias F");

  CD thriller = new CD("Thriller", 99, "Michael Jackson", 10);
  CD pearl = new CD("Pearl", 88, "Janis Joplin", 12);

  Magazine time = new Magazine("Time", 33, 2004, 52);
  Magazine wired = new Magazine("Wired", 44, 2004, 3);
*/
