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

Lecture 11: Who's Affraid of Abstractions? 
*/

/* 
Goals:

 - learn to abstract over lists with a list of Object
 - understand the benefits and limitations of such abstraction

Introduction:
Let us consider the following examples of classes that represent
images saved in a computer, items in a salad (tomaotes, peppers, 
mushrooms), or segments of a car trip between refueling, with 
information about the origin and destination, the miles traveled,
and the fuel information.

 +--------------+   +-------------+   +-------------+
 | Picture      |   | Item        |   | Segment     |
 +--------------+   +-------------+   +-------------+
 | String title |   | String name |   | String from |
 | int width    |   | int pieces  |   | String to   |
 | int height   |   | int price   |   | int miles   |
 +--------------+   +-------------+   | int gallons |
                                      | int price   |
                                      +-------------+

Here are some examples of the instances of these classes:

Picture snow  = new Picture("Snow.gif", 400, 200);
Picture beach = new Picture("Beach.gif", 200, 300);
Picture bluff = new Picture("Bluff.gif", 200, 600);

Item tom = new Item("tomato", 3, 50);
Item pep = new Item("pepper", 2, 60);
Item rad = new Item("raddish", 6, 10);

Segment b2n = new Segment("Boston", "NYC", 200, 10, 210);
Segment n2t = new Segment("NYC", "Trenton", 120, 5, 200);
Segment t2p = new Segment("Trenton", "Philly", 80, 2, 180);

We need a list of pictures to represent all pictures in a folder or 
a directory, we need a list of salad items to represent a
salas serving in a restaurant, and we need a list of trip 
segments, to compute the total distance traveled, or the cost
of the trip. The class diagrams for these classes are as follows:

        +------+                      +------+
        | ALoP |<------------+        | ALoI |<---------+
        +------+             |        +------+          |
          / \                |          / \             |
          ---                |          ---             |
           |                 |           |              |
      --------------         |      ------------        |  
      |            |         |      |          |        |
 +-------+ +---------------+ | +-------+ +------------+ | 
 | MTLoP | | ConsLoP       | | | MTLoI | | ConsLoI    | |
 +-------+ +---------------+ | +-------+ +------------+ |
           | Picture first | |           | Item first | | 
           | ALoP rest     |-+           | ALoI rest  |-+
           +---------------+             +------------+
   
        +------+                
        | ALoS |<------------+  
        +------+             |   
          / \                |  
          ---                |  
           |                 |    
      --------------         |   
      |            |         | 
 +-------+ +---------------+ |
 | MTLoS | | ConsLoS       | | 
 +-------+ +---------------+ | 
           | Segment first | | 
           | ALoP rest     |-+  
           +---------------+     
And the examples of lists are:

ALoP pictures = new ConsLoP(snow, 
                  new ConsLoP(beach,
                    new ConsLoP(bluff, 
                      new MTLoP()))));

ALoI salad = new ConsLoI(tom, 
               new ConsLoI(pep,
                 new ConsLoI(rad, 
                   new MTLoI()))));

ALoP trip = new ConsLoP(b2n, 
              new ConsLoP(n2t,
                new ConsLoP(t2p, 
                  new MTLoP()))));

It is clear, that this calls for abstraction. All three class diagrams
are nearly identical. The only difference is the type of data that is
the 'first' item in the list. In Java, the entire class hierarchy starts
with the class Object, and every class in Java extends Object. That means,
we can define instead a list of Object-s:
   
       +--------+                
       | ALoObj |<------------+  
       +--------+             |   
          / \                 |  
          ---                 |  
           |                  |    
      --------------          |   
      |            |          | 
 +---------+ +--------------+ |
 | MTLoObj | | ConsLoObj    | | 
 +---------+ +--------------+ | 
             | Object first | | 
             | ALoObj rest  |-+  
             +--------------+     

We now have to make sure we can define the same lists, using these 
classes. That part is easy:

ALoObj objPictures = new ConsLoObj(snow, 
                       new ConsLoObj(beach,
                         new ConsLoObj(bluff, 
                           new MTLoObj()))));

ALoObj objSalad = new ConsLoObj(tom, 
                    new ConsLoObj(pep,
                      new ConsLoObj(rad, 
                        new MTLoObj()))));

ALoObj objTrip = new ConsLoObj(b2n, 
                   new ConsLoObj(n2t,
                     new ConsLoObj(t2p, 
                       new MTLoObj()))));

Let us now design some methods for this class and see how it compares
with the methods we designed earlier. To count the number of elements
of a list we had the method count:

// in the class ALoP:
// count the number of elements in this list
abstract int count();

// in the class MTLoP:
int count() { return 0; }

// in the class ConsLoP:
int count() return 1 + this.rest.count(); }

The method is the same in the other two class hierarchies, and will 
look identical in the classes that represent a list of Object-s.
(We did not go through the whole design recipe, as we have seen this 
method several times already.)

---------------------------------------------------------------------------
***************************************************************************

Next, we would like to know whether the list contains the given object.
The purpose statement and the header for the method is 

// does this list contain the given object
boolean contains(Object obj)

Here are some examples:

pictures.contains(snow) --> should be true
pictures.contains(new Picture("Lake", 200, 200)) --> should be false

salad.contains(pep) --> should be true
salad.contains(new Item("Olive", 10, 10)) --> should be false

trip.contains(t2p) --> should be true
trip.contains(new Segment("DC", "Norfolk", 150, 8, 180)) --> should be false

Let us work on designing this method. In the abstract class, the purpose and 
the header will be as shown above, the only change being that the method is
declared to be abstract.

In the class that represents the empty list, there are no items to consider,
as an empty list does not contain any objects, and so the method always 
produces a 'false' value:

// in the class MTLoObj (or MTLoP, MTLoI, MTLoS)
boolean contains(Object obj){ return false; }

Let us design the method for each of the three specific nonempty lists:

// in the class ConsLoP:
boolean contains(Picture p){
  return this.first.equals(p)
      || this.rest.contains(p);
}

// in the class ConsLoI:
boolean contains(Item i){
  return this.first.equals(i)
      || this.rest.contains(i);
}

// in the class ConsLoS:
boolean contains(Segment s){
  return this.first.equals(s)
      || this.rest.contains(s);
}

The method 'equals' is defined in the class Object and so, if we replace the 
specific types of arguments with the 'generic' Object, the method will work
as well as it did before:

// in the class ConsLoObj:
boolean contains(Object o){
  return this.first.equals(o)
      || this.rest.contains(s);
}

We should rerun our earlier examples to make sure this abstraction works
as desired.

---------------------------------------------------------------------------
***************************************************************************

We now want to find more information about our lists. We are interested in 
the total size of all pictures we want to download, we need to know the
cost of the salad serving, and we are curious about the total distance we 
traveled on our trip.

We first need a method in the class Picture that computes its size, and 
a method in the class Item that computes teh cost of one item. As an 
exercise follow the design recipe to design these methods. The result will
be 

// in the class Picture:
// compute the size of this picure
int size(){ return this.width * this.height; }

// in the class Item: 
// compute the cost of this salad item
int cost(){ return this.pieces * this.price; }

We can now design the method totalSize in the classes that represent the 
list of pictures:

// in the class ALoP:
// compute the total size of all pictures in this list
abstract int totalSize();

Here is an example:
pictures.totalSize() == 260000;

We get:

// in the class MTLoP:
int totalSize(){ return 0;}

The template for the class ConsLoP is:

  ... this.first ...
  ... this.first.size() ...
  ... this.rest ...
  ... this.rest.totalSize() ...

and the method body becomes:

// in the class ConsLoP:
int totalSize(){
  return this.first.size()
       + this.rest.totalSize();
}

We can now design the method totalCost in the classes that represent the 
list of salad items:

// in the class ALoI:
// compute the total cost of all items in this list
abstract int totalCost();

Here is an example:
salad.totalCost() == 330;

We get:

// in the class MTLoI:
int totalSize(){ return 0;}

The template for the class ConsLoI is:

  ... this.first ...
  ... this.first.cost() ...
  ... this.rest ...
  ... this.rest.totalCost() ...

and the method body becomes:

// in the class ConsLoI:
int totalCost(){
  return this.first.cost()
       + this.rest.totalCost();
}

We can now design the method totalDistance in the classes that represent the 
list of trip segments:

// in the class ALoS:
// compute the total distance of all trip segments in this list
abstract int totalDistance();

Here is an example:
trip.totalDistance() == 400;

We get:

// in the class MTLoS:
int totalDistance(){ return 0;}

The template for the class ConsLoS is:

  ... this.first ...
  ... this.first.miles ... (as well as other field selectorss...)
  ... this.rest ...
  ... this.rest.totalDistance() ...

and the method body becomes:

// in the class ConsLoS:
int totalDistance(){
  return this.first.miles
       + this.rest.totalDistance();
}

We see that the only differences are in the Cons--- classes, and even there
only in the part that determines the value of the first item: its size, its
cost, or the distance it represents. We can rename the methods 'size' and 
'cost' to 'value', and add a similar method to the class Segment as follows:

// in the class Picture:
int value(){ return this.width * this.height; }


// in the class Item:
int value(){return this.pieces * this.price; }


// in the class Segment:
int value(){ return this.miles; }

We can then try to abstract the methods 'totalSize', 'totalCost', and 
'totalDistance' into a method 'totalValue' in the classes that represent
a list of Object-s. We get:

// in the class ALoObj:
// compute the total value of all elements in this list
abstract int totalValue();

Here are our examples:
objPictures.totalValue() == 260000;
objSalad.totalValue() == 330 
objTrip.totalValue() == 400;

We get:

// in the class MTLoS:
int totalDistance(){ return 0;}

The template for the class ConsLoObj is:

  ... this.first ...
  ... this.rest ...
  ... this.rest.totalValue() ...

If we could include in the template ... this.first.value() ...
our method body would be:

// in the class ConsLoObj:
int totalValue(){
  return this.first.value()
       + this.rest.totalValue();
}

But we have a problem. Not every class whose instances that can be included 
in this list contains the method 'value'. On the other hand, the three
classes Picture, Item, and Segment have nothing else in common. There is
no reason to define a common superclass, as this one method is the only
feature they share. We need a way to express the fact that these three 
classes share a common functional behavior and to indicate in the method
'totalValue' in the class ConsLoObj that the 'this.first' object has 
this behavior.

There are three parts to this 'contractual obligation':

First, we define an interface (the contractual behavior) as follows:

interface IValue{
  // produce a value of this object
  int value();
}

It looks like a definition of an abstract class, but contains no fields. While
each class can extend only one super class, it may implement several different
interfaces, as they impose no restrictions on the kind of data that the class
represents --- it only requires that a specified behavior is implemented.

As a second part of our contractual obligation, the three classes declare their
intent to implement the 'value' emthod with the specified header. Our three class 
definitions will then start with:

// to represent a picture in a file directory
class Picture implements IValue{...

// to represent an item in a salad serving
class Item implements IValue{...

// to represent a segment of a car trip
class Segment implements IValue{...

Java compiler can now verify that a method 'value' with the required header
is indeed defined in each of these classes.

The final part of our contract is the requirement in the implementation
of the 'totalValue' method that only instances of this.first for which
this.first.value() is invoked are those that belong to classes that implement 
the 'value' metod. This is specified as follows:

// in the class ConsLoObj:
int totalValue(){
  return ((IValue)this.first).value()
       + this.rest.totalValue();
}

The term ((IValue)this.first) specifies that this.first must be of the type
IValue. Once that is assured, we know that the method 'value' has been 
implemented for this.first and the rest of the computation can proceed safely.

Notice that we used the word 'type'. An instance of a class has a type that
is the combination of its class, all of its super classes, and of all the 
interfaces it implements. It defines all the fields that this instance can 
access, and all methods that this instance can invoke.

We conclude with a complete working code for these classes and the list of 
objects, together with the interface IValue.

*/
/*
     +------------------+
     | Interface IValue |<- - - - - - - +
     +------------------+               |
     | int value()      |
     +------------------+               |

          +- - - - - - - - +- - - - - - + - -+

          |                |                 |          
 +--------------+   +-------------+   +-------------+
 | Picture      |   | Item        |   | Segment     |
 +--------------+   +-------------+   +-------------+
 | String title |   | String name |   | String from |
 | int width    |   | int pieces  |   | String to   |
 | int height   |   | int price   |   | int miles   |
 +--------------+   +-------------+   | int gallons |
 | int value()  |   | int value() |   | int price   |
 +--------------+   +-------------+   +-------------+
                                      | int value() |
                                      +-------------+

  
  +--------------------------+                
  | ALoObj                   |<--------------+  
  +--------------------------+               |   
  |abstract int totalValue() |               |   
  +--------------------------+               |   
            / \                              |  
            ---                              |  
             |                               |    
      -------------------                    |   
      |                 |                    | 
 +------------------+ +------------------+   |
 | MTLoObj          | | ConsLoObj        |   | 
 +------------------+ +------------------+   | 
 | int totalValue() | | Object first     |   | 
 +------------------+ | ALoObj rest      |---+  
                      +------------------+  
                      | int totalValue() |   
                      +------------------+  

*/

/*
;                                             
;                                             
;                                             
;   ;  ;     ;          ;                     
;   ;  ;     ;          ;                     
;   ;   ;   ;           ;                     
;   ;   ;   ;    ;;;    ;   ;   ;    ;;;      
;   ;   ;   ;   ;   ;   ;   ;   ;   ;   ;     
;   ;    ; ;        ;   ;   ;   ;  ;    ;     
;   ;    ; ;     ;;;;   ;   ;   ;  ;;;;;;     
;   ;    ; ;    ;   ;   ;   ;   ;  ;          
;   ;     ;     ;   ;   ;   ;  ;;   ;         
;   ;     ;      ;;;;;  ;    ;; ;    ;;;;     
;                                             
;                                             
;                                             
*/
interface IValue{
  // produce a value of this object
  int value();
}

/*
;                                                 
;                                                 
;                                                 
;   ;;;;;  ;                                      
;   ;    ;                                        
;   ;    ;            ;                           
;   ;    ; ;    ;;;  ;;;;  ;   ;   ; ;   ;;;      
;   ;    ; ;   ;   ;  ;    ;   ;   ;;   ;   ;     
;   ;;;;;  ;  ;       ;    ;   ;   ;   ;    ;     
;   ;      ;  ;       ;    ;   ;   ;   ;;;;;;     
;   ;      ;  ;       ;    ;   ;   ;   ;          
;   ;      ;   ;   ;  ;    ;  ;;   ;    ;         
;   ;      ;    ;;;    ;;   ;; ;   ;     ;;;;     
;                                                 
;                                                 
;                                                 
*/
// to represent a picture in a file directory
class Picture implements IValue{
  String title;
  int width;
  int height;

  Picture(String title, int width, int height) {
    this.title = title;
    this.width = width;
    this.height = height;
  }

  // compute the size of this picture
  int value(){
    return this.width * this.height;
  }

/*
  // ** DRAFT TEMPLATE ** Edit as needed.
  ??? mmm() {
    ... this.title ...
    ... this.width ...
    ... this.height ...
    ... this.value() ...
  }
*/
}

/*
;                                  
;                                  
;                                  
;   ;                              
;   ;                              
;   ;   ;                          
;   ;  ;;;;   ;;;   ; ;;  ;;       
;   ;   ;    ;   ;  ;;  ;;  ;      
;   ;   ;   ;    ;  ;   ;   ;      
;   ;   ;   ;;;;;;  ;   ;   ;      
;   ;   ;   ;       ;   ;   ;      
;   ;   ;    ;      ;   ;   ;      
;   ;    ;;   ;;;;  ;   ;   ;      
;                                  
;                                  
;                                  
*/
// to represent a salad item
class Item implements IValue{
  String name;
  int pieces;
  int price;

  Item(String name, int pieces, int price) {
    this.name = name;
    this.pieces = pieces;
    this.price = price;
  }

  // compute the cost of this salad ingredients
  int value(){
   return this.pieces * this.price;
  }

/*
  // ** DRAFT TEMPLATE ** Edit as needed.
  ??? mmm() {
    ... this.name ...
    ... this.pieces ...
    ... this.price ...
    ... this.value() ...
  }
*/
}


/*
;                                                            
;                                                            
;                                                            
;    ;;;;                                                    
;   ;    ;                                                   
;   ;                                                ;       
;   ;       ;;;    ;; ;   ; ;;  ;;     ;;;   ; ;;   ;;;;     
;    ;;    ;   ;  ;  ;;   ;;  ;;  ;   ;   ;  ;;  ;   ;       
;      ;  ;    ; ;    ;   ;   ;   ;  ;    ;  ;   ;   ;       
;       ; ;;;;;; ;    ;   ;   ;   ;  ;;;;;;  ;   ;   ;       
;       ; ;      ;    ;   ;   ;   ;  ;       ;   ;   ;       
;   ;   ;  ;      ;  ;;   ;   ;   ;   ;      ;   ;   ;       
;    ;;;    ;;;;   ;; ;   ;   ;   ;    ;;;;  ;   ;    ;;     
;                     ;                                      
;                ;    ;                                      
;                 ;;;;                                       
*/
// to represent one segment of a road trip
class Segment implements IValue{
  String from;
  String to;
  int miles;
  int gallons;
  int price;

  Segment(String from, String to, int miles, int gallons, int price) {
    this.from = from;
    this.to = to;
    this.miles = miles;
    this.gallons = gallons;
    this.price = price;
  }

  int value(){
    return this.miles;
  }

/*
  // ** DRAFT TEMPLATE ** Edit as needed.
  ??? mmm() {
    ... this.from ...
    ... this.to ...
    ... this.miles ...
    ... this.gallons ...
    ... this.price ...
    ... this.value() ...
  }
*/
}


/*
;                                                    
;                                                    
;                                                    
;      ;     ;                ;;;;    ;       ;      
;      ;     ;               ;    ;   ;              
;     ; ;    ;              ;      ;  ;              
;     ; ;    ;       ;;;    ;      ;  ; ;;    ;      
;    ;   ;   ;      ;   ;   ;      ;  ;;  ;   ;      
;    ;   ;   ;     ;     ;  ;      ;  ;    ;  ;      
;   ;;;;;;;  ;     ;     ;  ;      ;  ;    ;  ;      
;   ;     ;  ;     ;     ;  ;      ;  ;    ;  ;      
;   ;     ;  ;      ;   ;    ;    ;   ;;  ;   ;      
;  ;       ; ;;;;;;  ;;;      ;;;;    ; ;;    ;      
;                                             ;      
;                                             ;      
;                                           ;;       
*/
// to represent a list of objects
abstract class ALoObj {

  // count the number of elements in this list
  abstract int count();

  // does this list contain the given object
  abstract boolean contains(Object obj);

  // compute the total value of all objects in this list
  abstract int totalValue();

/*
  // ** DRAFT TEMPLATE ** Edit as needed.
  // purpose statement 
  abstract ??? mmm();
*/
}

/*
;                                                              
;                                                              
;                                                              
;   ;       ; ;;;;;;;  ;                ;;;;    ;       ;      
;   ;;     ;;    ;     ;               ;    ;   ;              
;   ;;     ;;    ;     ;              ;      ;  ;              
;   ; ;   ; ;    ;     ;       ;;;    ;      ;  ; ;;    ;      
;   ; ;   ; ;    ;     ;      ;   ;   ;      ;  ;;  ;   ;      
;   ;  ; ;  ;    ;     ;     ;     ;  ;      ;  ;    ;  ;      
;   ;  ; ;  ;    ;     ;     ;     ;  ;      ;  ;    ;  ;      
;   ;   ;   ;    ;     ;     ;     ;  ;      ;  ;    ;  ;      
;   ;   ;   ;    ;     ;      ;   ;    ;    ;   ;;  ;   ;      
;   ;       ;    ;     ;;;;;;  ;;;      ;;;;    ; ;;    ;      
;                                                       ;      
;                                                       ;      
;                                                     ;;       
*/
// to represent an empty list of objects
class MTLoObj extends ALoObj {
  MTLoObj() {}

  int count() { return 0; }

  boolean contains(Object o){ return false; }

  int totalValue(){ return 0; }

/*
  // ** DRAFT TEMPLATE ** Edit as needed.
  ??? mmm() {
    ... this.mmm() ...
    ... this.count() ...
    ... this.contains(Object o) ...
    ... this.value() ...
  }
*/
}

/*
;                                                                           
;                                                                           
;                                                                           
;     ;;;;                          ;                ;;;;    ;       ;      
;    ;    ;                         ;               ;    ;   ;              
;   ;                               ;              ;      ;  ;              
;   ;         ;;;    ; ;;     ;;;   ;       ;;;    ;      ;  ; ;;    ;      
;   ;        ;   ;   ;;  ;   ;      ;      ;   ;   ;      ;  ;;  ;   ;      
;   ;       ;     ;  ;   ;   ;;     ;     ;     ;  ;      ;  ;    ;  ;      
;   ;       ;     ;  ;   ;    ;;    ;     ;     ;  ;      ;  ;    ;  ;      
;   ;       ;     ;  ;   ;      ;   ;     ;     ;  ;      ;  ;    ;  ;      
;    ;    ;  ;   ;   ;   ;      ;   ;      ;   ;    ;    ;   ;;  ;   ;      
;     ;;;;    ;;;    ;   ;   ;;;    ;;;;;;  ;;;      ;;;;    ; ;;    ;      
;                                                                    ;      
;                                                                    ;      
;                                                                  ;;       
*/
// to represent a nonempty list of objects
class ConsLoObj extends ALoObj {
  Object first;
  ALoObj rest;

  ConsLoObj(Object first, ALoObj rest) {
    this.first = first;
    this.rest = rest;
  }

  int count() { return 1 + this.rest.count(); }

  boolean contains(Object o){
    return this.first.equals(o)
       || this.rest.contains(o);
  }

  int totalValue(){
    return ((IValue)this.first).value()
         + this.rest.totalValue();
  }

/*
  // ** DRAFT TEMPLATE ** Edit as needed.
  ??? mmm() {
    ... this.first ...
    ... this.rest.mmm() ...
    ... this.count() ...
    ... this.contains(Object o) ...
    ... this.totalValue() ...
  }
*/
}






/*
;                                                                  
;                                                                  
;                                                                  
;   ;;;;;;                                    ;                    
;   ;                                         ;                    
;   ;                                         ;                    
;   ;     ;     ;  ;;;    ; ;;  ;;    ; ;;    ;    ;;;    ;;;      
;   ;;;;;  ;   ;  ;   ;   ;;  ;;  ;   ;;  ;   ;   ;   ;  ;         
;   ;       ; ;       ;   ;   ;   ;   ;    ;  ;  ;    ;  ;;        
;   ;        ;     ;;;;   ;   ;   ;   ;    ;  ;  ;;;;;;   ;;       
;   ;       ; ;   ;   ;   ;   ;   ;   ;    ;  ;  ;          ;      
;   ;      ;   ;  ;   ;   ;   ;   ;   ;;  ;   ;   ;         ;      
;   ;;;;;;;     ;  ;;;;;  ;   ;   ;   ; ;;    ;    ;;;;  ;;;       
;                                     ;                            
;                                     ;                            
;                                     ;                            
*/
class Examples{
  Examples() {}

  Picture snow  = new Picture("Snow.gif", 400, 200);
  Picture beach = new Picture("Beach.gif", 200, 300);
  Picture bluff = new Picture("Bluff.gif", 200, 600);

  Item tom = new Item("tomato", 3, 50);
  Item pep = new Item("pepper", 2, 60);
  Item rad = new Item("raddish", 6, 10);

  Segment b2n = new Segment("Boston", "NYC", 200, 10, 210);
  Segment n2t = new Segment("NYC", "Trenton", 120, 5, 200);
  Segment t2p = new Segment("Trenton", "Philly", 80, 2, 180);


  ALoObj objPictures = new ConsLoObj(snow, 
                         new ConsLoObj(beach,
                           new ConsLoObj(bluff, 
                             new MTLoObj())));

  ALoObj objSalad = new ConsLoObj(tom, 
                      new ConsLoObj(pep,
                        new ConsLoObj(rad, 
                          new MTLoObj())));

  ALoObj objTrip = new ConsLoObj(b2n, 
                     new ConsLoObj(n2t,
                       new ConsLoObj(t2p, 
                         new MTLoObj())));

  // test the method count
  boolean testCount1 = objPictures.count() == 3;
  boolean testCount2 = objSalad.count() == 3;
  boolean testCount3 = objTrip.count() == 3;

  // test the method contains
  boolean testContains1 = objPictures.contains(snow) == true;
  boolean testContains2 = objPictures.contains(new Picture("Lake", 200, 200)) == false;

  boolean testContains3 = objSalad.contains(pep) == true;
  boolean testContains4 = objSalad.contains(new Item("Olive", 10, 10)) == false;

  boolean testContains5 = objTrip.contains(t2p) == true;
  boolean testContains6 = objTrip.contains(new Segment("DC", "Norfolk", 150, 8, 180)) == false;

  boolean testTotalValue1 = objPictures.totalValue() == 260000;
  boolean testTotalValue2 = objSalad.totalValue() == 330;
  boolean testTotalValue3 = objTrip.totalValue() == 400;
}

   

