Abstracting over the behavior

Code for this part of the lecture can be found here.

In the previous lecture we have seen that the common functional interface for several classes allows us to abstract not only over the definition of two lists, but also over their comparison, and even over a common mehtod.

Consider the following class diagram:

             +---------------------------+                
             |  AList                    |                
             +---------------------------+                
	     | boolean same(Obj that)    |
	     | boolean contains(Obj that)| 
             +---------------------------+                
                         |                    
                        / \                   
                        ---                   
                         |                    
           ---------------------------          
           |                         |          
    +-------------+          +---------------+  
    | MTList      |          | ConsList      |  
    +-------------+          +---------------+  
    +-------------+     +----| ISame fist    | 
                        |    | AList rest    |   
                        |    +---------------+ 
			v
            +-------------------------+ 
            | ISame                   |   
	    +-------------------------+
	    | boolean same(ISame that)|
	    +-------------------------+
                        |
                       / \
                       ---
                        |
               --------------------
               |                  |
	+--------------+    +--------------+
	| Book         |    | Song         |
        +--------------+    +--------------+
        | String title |    | String title | 
	| String author|    | int    time  |
	| int    year  |    +--------------+  
        +--------------+    
           
            
    

We would like to design a method that returns true if this AList contains a Book written before 1950. Otherwise it returns false.

In class MTList we add the following piece of code:

    //is there a book in this list written before 1950   
    boolean hasOldBook(){ 
     return false; 
  } 
    

In class ConsList we add the following piece of code:

    //is there a book in this list written before 1950   
    boolean hasOldBook(){ 
     if ((Book)this.first.year<1950)
            return true;
     else  
	    return this.rest.hasOldBook()
  } 
    

Note:if the first element of this AList is not a Book, JAVA will raise an exception

We would like also to design a method that returns true if this AList contains a Book written by GBS. Otherwise it returns false.

In class MTList we add the following piece of code:

    //is there a book in this list written by GBS   
    boolean hasGBSBook(){ 
     return false; 
  } 
    

In class ConsList we add the following piece of code:

    //is there a book in this list written by GBS   
    boolean hasGBSBook(){ 
     if ((Book)this.first.author.equals("GBS"))
            return true;
     else  
	    return this.rest.hasGBSBook()
  } 
    

It is obvious that there are many structural similarities between the two methods. So we can abstract over those similarities and a design a method that checks if this AList contains an element that satisfies a given predicate.

In order to do that we need to extend our class diagram:

                     +---------------------------+                
                     |    ISelect                |                
		     +---------------------------+
                     | boolean select(Object obj)|		
		     +---------------------------+                
                                  |                    
                                 / \                   
                                 ---                   
                                  |                    
                     ----------------------------          
                     |            |             |          
               +----------+   +---------+   +---------+  
               | LongSong |   | GBSBook |   | OldBook |  
               +----------+   +---------+   +---------+
	       +----------+   +---------+   |int year |
                                            +---------+   
    

Now, we can designour genral method that returns true if this AList contains an element that satisfies the given predicate. Otherwise it returns false.

In class MTList we add the following piece of code:

    //is there an element in this list that satisfies pred    
    boolean anysuch(ISelect pred){ 
     return false; 
  } 
    

In class ConsList we add the following piece of code:

    //is there an element in this list that satisfies pred   
    boolean anysuch(ISelect pred){ 
     if (pred.select(this.first))
            return true;
     else  
	    return this.rest.anysuch(pred)
  } 
    

We also need to design our predicates.

In class LongSong we add the following piece of code:

    //does the given song last more than 30 sec   
    boolean select(Object obj){ 
     return (((Song)obj).time>30); 
  } 
    

In class GBSBook we add the following piece of code:

    //is the given book written by GBS   
    boolean select(Object obj){ 
     return (((Book)obj).author.equals("GBS")); 
  } 
    

In class OldBook we add the following piece of code:

    //is the given book written befor this year   
    boolean select(Object obj){ 
     return (this.year>((Book)obj).year); 
  } 

    

We can now write examples of the form:

    songlist.anysuch(new LongSong());
    booklist.anysuch(new GBSBook());
    booklist.anysuch(new OldBook(1920));