Differences
This shows you the differences between two versions of the page.
| Next revision | Previous revision | ||
|
fp2025:lab09 [2026/05/16 22:57] silviu created |
fp2025:lab09 [2026/05/16 23:16] (current) silviu |
||
|---|---|---|---|
| Line 9: | Line 9: | ||
| *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 52: | ||
| </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 92: | ||
| 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.length} matches.") |
| } | } | ||
| } | } | ||
| </code> | </code> | ||
| + | |||
| + | 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 none don't. | **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. | ||
| Line 109: | Line 111: | ||
| - | **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 117: | ||
| 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 132: | ||
| } | } | ||
| } | } | ||
| + | </code> | ||