Skip to content

Commit 686b631

Browse files
author
Rafa Paradela
committed
Merge pull request scala-exercises#49 from hasumedic/type-variance
Typos around typevariance
2 parents 0d76f35 + 103104a commit 686b631

File tree

1 file changed

+4
-4
lines changed

1 file changed

+4
-4
lines changed

app/json/typevariance.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,23 +26,23 @@
2626
"postparagraph": ""
2727
},
2828
{
29-
"preparagraph": "Scala's type system has to account for class hierarchies together with polymorphism. Class hierarchies allow the expression of subtype relationships. A central question that comes up when mixing OO with polymorphism is: if `T'` is a subclass of `T`, is `Container[T']` considered a subclass of `Container[T]`? Variance annotations allow you to express the following relationships between class hierarchies & polymorphic types:\n\n####Covariant:\n- `C[T']` is a subclass of `C[T]`\n- Scala notation: `[+T]`\n\n####Contravariant:\n- `C[T]` is a subclass of `C[T']`\n- Scala notation: `[-T]` \n\n####Invariant:\n- `C[T]` and `C[T']` are not related\n- Scala notation: `[T]` \n\n\nThat one probably blew your mind. Now if you assign a type to the instantiation, that's different to the variable type, you'll have problems. You may want to take time after this o compare this koan with the previous koan to compare and contrast. \n\n```\nclass MyContainer[A](a: A)(implicit manifest: scala.reflect.Manifest[A]) {\n private[this] var item = a\n\n def get = item\n\n def set(a: A) {\n item = a\n }\n\n def contents = manifest.runtimeClass.getSimpleName\n}\n\n// Uncomment the following line\n// val fruitBasket:MyContainer[Fruit] = new MyContainer[Orange](new Orange())\n```\n\nSo, if you want to set a Fruit basket to an orange basket so how do we fix that? You make it covariant using `+`. This will allow you to set the your container to a either a variable with the same type or parent type. In other words, you can assign `MyContainer[Fruit]` or `MyContainer[Citrus]`.",
29+
"preparagraph": "Scala's type system has to account for class hierarchies together with polymorphism. Class hierarchies allow the expression of subtype relationships. A central question that comes up when mixing OO with polymorphism is: if `T'` is a subclass of `T`, is `Container[T']` considered a subclass of `Container[T]`? Variance annotations allow you to express the following relationships between class hierarchies & polymorphic types:\n\n####Covariant:\n- `C[T']` is a subclass of `C[T]`\n- Scala notation: `[+T]`\n\n####Contravariant:\n- `C[T]` is a subclass of `C[T']`\n- Scala notation: `[-T]` \n\n####Invariant:\n- `C[T]` and `C[T']` are not related\n- Scala notation: `[T]` \n\n\nThat one probably blew your mind. Now if you assign a type to the instantiation that is different to the variable type, you'll have problems. You may want to take time after this koan to compare and contrast with the previous one. \n\n```\nclass MyContainer[A](a: A)(implicit manifest: scala.reflect.Manifest[A]) {\n private[this] var item = a\n\n def get = item\n\n def set(a: A) {\n item = a\n }\n\n def contents = manifest.runtimeClass.getSimpleName\n}\n\n// Uncomment the following line\n// val fruitBasket:MyContainer[Fruit] = new MyContainer[Orange](new Orange())\n```\n\nSo, how do we get to set set a Fruit basket to an Orange basket? You make it covariant using `+`. This will allow you to set the container to either a variable with the same type or parent type. In other words, you can assign `MyContainer[Fruit]` or `MyContainer[Citrus]`.",
3030
"code": "class MyContainer[+A](a: A)(implicit manifest: scala.reflect.Manifest[A]) {\n private[this] val item = a\n\n def get = item\n\n def contents = manifest.runtimeClass.getSimpleName\n}\n\nval fruitBasket: MyContainer[Fruit] = new MyContainer[Orange](new Orange())\nfruitBasket.contents should be(__)",
3131
"solutions": [
3232
"\"Orange\""
3333
],
3434
"postparagraph": ""
3535
},
3636
{
37-
"preparagraph": "The problem with covariance is that you can't mutate, set, or change the object since it has to guarantee that what you put in has to be that type. In other words the reference is a fruit basket, but we still have to make sure that no other fruit can be placed in our orange basket:",
37+
"preparagraph": "The problem with covariance is that you can't mutate, set or change the object since it has to guarantee that what you put into it is a valid type. In other words the reference is a fruit basket, but we still have to make sure that no other fruit can be placed in our orange basket:",
3838
"code": "class MyContainer[+A](a: A)(implicit manifest: scala.reflect.Manifest[A]) {\n private[this] val item = a\n\n def get = item\n\n def contents = manifest.runtimeClass.getSimpleName\n}\n\nval fruitBasket: MyContainer[Fruit] = new MyContainer[Orange](new Orange())\nfruitBasket.contents should be(__)\n\nclass NavelOrange extends Orange //Creating a subtype to prove a point\n//val navelOrangeBasket: MyContainer[NavelOrange] = new MyContainer[Orange](new Orange()) //Bad!\n//val tangeloBasket: MyContainer[Tangelo] = new MyContainer[Orange](new Orange()) //Bad!",
3939
"solutions": [
4040
"\"Orange\""
4141
],
4242
"postparagraph": ""
4343
},
4444
{
45-
"preparagraph": "Declaring - indicates contravariance variance. Using - you can apply any container with a certain type to a container with a superclass of that type. This is reverse to covariant. In our example, we can set a citrus basket to an orange or tangelo basket. Since an orange or tangelo basket is a citrus basket. Contravariance is the opposite of covariance:",
45+
"preparagraph": "Declaring - indicates contravariance variance. Using - you can apply any container with a certain type to a container with a superclass of that type. This is reverse to covariant. In our example, we can set a citrus basket to an orange or tangelo basket. Since an orange or tangelo basket are a citrus basket. Contravariance is the opposite of covariance:",
4646
"code": "class MyContainer[-A](a: A)(implicit manifest: scala.reflect.Manifest[A]) {\n private[this] var item = a\n\n def set(a: A) {\n item = a\n }\n\n def contents = manifest.runtimeClass.getSimpleName\n}\n\nval citrusBasket: MyContainer[Citrus] = new MyContainer[Citrus](new Orange)\ncitrusBasket.contents should be(__)\nval orangeBasket: MyContainer[Orange] = new MyContainer[Citrus](new Tangelo)\norangeBasket.contents should be(__)\nval tangeloBasket: MyContainer[Tangelo] = new MyContainer[Citrus](new Orange)\ntangeloBasket.contents should be(__)\n\nval orangeBasketReally: MyContainer[Orange] = tangeloBasket.asInstanceOf[MyContainer[Orange]]\norangeBasketReally.contents should be(__)\norangeBasketReally.set(new Orange())",
4747
"solutions": [
4848
"\"Citrus\"",
@@ -80,4 +80,4 @@
8080
"postparagraph": ""
8181
}
8282
]
83-
}
83+
}

0 commit comments

Comments
 (0)