Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
fp2025:lab09 [2026/05/16 22:57]
silviu created
fp2025:lab09 [2026/05/21 18:08] (current)
silviu
Line 6: Line 6:
   * get yourself familiar with covariance and contravariance   * get yourself familiar with covariance and contravariance
   * see the benefits of using these concepts   * see the benefits of using these concepts
 +  * understand bounded generics
  
-*Introduction*+**Introduction**
  
-When we define a generic type, for example ''​Box[T]'',​ and we have a types ''​Animal''​ and ''​Dog''​ and ''​Dog extends Animal'',​ the type ''​Shelter[Dog]''​ does not extend type ''​Shelter[Animal]''​. However, sometimes we would like to have a conversion in one direction or the other. For example, consider the following code:+When we define a generic type, for example ''​Shelter[T]'',​ and we have a types ''​Animal''​ and ''​Dog''​ and ''​Dog extends Animal'',​ the type ''​Shelter[Dog]''​ does not extend type ''​Shelter[Animal]''​. However, sometimes we would like to have a conversion in one direction or the other. For example, consider the following code:
  
 <code scala> <code scala>
Line 52: Line 53:
 </​code>​ </​code>​
  
-**9.2.** Modify this type to use the correct variance:+**9.2.** Modify this type to use the correct variance ​to the generic parameter:
  
 <code scala> <code scala>
Line 92: Line 93:
       println(" ​ -> No animals matched this criteria."​)       println(" ​ -> No animals matched this criteria."​)
     } else {     } else {
-      ​matches.foreach(animal => println(s" ​ -> MATCH: ​${animal.name}"))+      println(s" ​ -> There were ${matches.lengthmatches.")
     }     }
 } }
 </​code>​ </​code>​
  
-**9.6.** Apply the ''​crossJoinAndFilter''​ method on every possible shelter-predicate combination from the previous exercises, note which ones compile and which none don't.+Notice the invariance of the generic parameter, it will come up in the last exercise. 
 + 
 +**9.6.** Apply the ''​crossJoinAndFilter''​ method on every possible shelter-predicate combination from the previous exercises, note which ones compile and which ones don't.
  
 **9.7.** Complete the following code and use the proper bound and use it on some shelter: **9.7.** Complete the following code and use the proper bound and use it on some shelter:
Line 109: Line 112:
  
  
-**9.7.** Complete the following code and use the proper bound to implement it, start from a shelter for ''​Corgi''​ and then expand it by adding new types of residents:+**9.8.** Complete the following code and use the proper bound to implement it, start from a shelter for ''​Corgi''​ and then expand it by adding new types of residents:
  
 <code scala> <code scala>
Line 115: Line 118:
  
 def saveAnimal[???​T???​](newResident:​ T): Shelter[T] = { def saveAnimal[???​T???​](newResident:​ T): Shelter[T] = {
-    //Create ​a new shelter by adding ​the new resident+    // Returns ​a new Shelter[T] containing the old residents + the new resident
 } }
 </​code>​ </​code>​
  
-**9.8.** Apply the proper generic types to this function and test it, ''​S''​ is the type of residents in the shelter and ''​P''​ is the type to test in the predicate, chose the proper bound:+**9.9.** Apply the proper generic types to this function and test it, ''​S''​ is the type of residents in the shelter and ''​P''​ is the type to test in the predicate, chose the proper bound:
  
 +<code scala>
 def safeCrossJoin[???​](shelter:​ Shelter[S], predicate: Predicate[P]):​ Unit = { def safeCrossJoin[???​](shelter:​ Shelter[S], predicate: Predicate[P]):​ Unit = {
   println(s"​Safely filtering ${shelter.name}:"​)   println(s"​Safely filtering ${shelter.name}:"​)
Line 129: Line 133:
   }   }
 } }
 +</​code>​