Skip to content

Commit 1ad1a91

Browse files
address review comments
1 parent 8cb4419 commit 1ad1a91

File tree

1 file changed

+10
-10
lines changed

1 file changed

+10
-10
lines changed

_tour/variances.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ previous-page: generic-classes
1010
redirect_from: "/tutorials/tour/variances.html"
1111
---
1212

13-
Variance is a property of parameterized types that relates the subtyping relationship of parameterized types to the subtyping releationship of its type parameter. Scala supports variance annotations of type parameters of [generic classes](generic-classes.html), to allow them to be covariant, contravariant, or invariant if no annotations are used. The use of variance in the type system allows us to make intuitive connections between complex types.
13+
Variance lets you control how type parameters behave with regards to subtyping. Scala supports variance annotations of type parameters of [generic classes](generic-classes.html), to allow them to be covariant, contravariant, or invariant if no annotations are used. The use of variance in the type system allows us to make intuitive connections between complex types.
1414

1515
```scala mdoc
1616
class Foo[+A] // A covariant class
@@ -20,7 +20,7 @@ class Baz[A] // An invariant class
2020

2121
### Invariance
2222

23-
By default, type paramters in scala are invariant: subtyping relationships between the type paramter aren't reflected in the parameterized type. To explore why this works the way it does, we look at a simple parameterized type, the mutable box.
23+
By default, type parameters in Scala are invariant: subtyping relationships between the type parameters aren't reflected in the parameterized type. To explore why this works the way it does, we look at a simple parameterized type, the mutable box.
2424

2525
```scala mdoc
2626
class Box[A](var content: A)
@@ -39,27 +39,27 @@ case class Dog(name: String) extends Animal
3939
We can say that `Cat` is a subtype of `Animal`, and that `Dog` is also a subtype of `Animal`. That means that the following is well-typed:
4040

4141
```scala mdoc
42-
val myAnimal: Animal = Cat("felix")
42+
val myAnimal: Animal = Cat("Felix")
4343
```
4444

45-
What about boxes? If I have a `Box[Cat]`, is it a subtype of `Box[Animal]`, like `Cat` is a subtype of `Animal`? At first sight, it looks like that may be plausible, but if we try to do that, the compiler will tell us we have an error:
45+
What about boxes? Is `Box[Cat]` a subtype of `Box[Animal]`, like `Cat` is a subtype of `Animal`? At first sight, it looks like that may be plausible, but if we try to do that, the compiler will tell us we have an error:
4646

4747
```scala
48-
val myCatBox: Box[Cat] = new Box[Cat](Cat("felix"))
48+
val myCatBox: Box[Cat] = new Box[Cat](Cat("Felix"))
4949
val myAnimalBox: Box[Animal] = myCatBox // this doesn't compile
5050
val myAnimal: Animal = myAnimalBox.content
5151
```
5252

5353
Why could this be a problem? We can get the cat from the box, and it's still an Animal, isn't it? Well, yes. But that's not all we can do. We can also replace the cat in the box with a different animal
5454

5555
```scala
56-
mayAnimalBox.content = Dog("fido")
56+
mayAnimalBox.content = Dog("Fido")
5757
```
5858

59-
There now is a Dog in the Animal box. That's all fine, you can put Dogs in Animal boxes, because Dogs are Animals. But our Animal Box is a Cat Box! You can't put a Dog in a Cat box. If we could, and then try to get the cat from our catbox, it would turn out to be a dog, breaking type soundness.
59+
There now is a Dog in the Animal box. That's all fine, you can put Dogs in Animal boxes, because Dogs are Animals. But our Animal Box is a Cat Box! You can't put a Dog in a Cat box. If we could, and then try to get the cat from our Cat Box, it would turn out to be a dog, breaking type soundness.
6060

6161
```scala
62-
val myCat: Cat = myCatBox.content //myCat would be fido the dog!
62+
val myCat: Cat = myCatBox.content //myCat would be Fido the dog!
6363
```
6464

6565
From this, we have to conclude that `Box[Cat]` and `Box[Animal]` can't have a subtyping relationship, even though `Cat` and `Animal` do.
@@ -100,7 +100,7 @@ printAnimalNames(dogs)
100100

101101
### Contravariance
102102

103-
We've seen we can accomplish Covariance by making sure that we can't put something in the Covariant type, but only get something out. What if we had the opposite, something you can put something in, but can't take out? This situation arises if we have something like a serializer, that takes values of type A, and converts them to a serialized format.
103+
We've seen we can accomplish covariance by making sure that we can't put something in the covariant type, but only get something out. What if we had the opposite, something you can put something in, but can't take out? This situation arises if we have something like a serializer, that takes values of type A, and converts them to a serialized format.
104104

105105
```scala mdoc
106106
abstract class Serializer[-A] {
@@ -122,4 +122,4 @@ More formally, that gives us the reverse relationship: given some `class Contra[
122122

123123
Variance is supported in different ways by some languages that are similar to Scala. For example, variance annotations in Scala closely resemble those in C#, where the annotations are added when a class abstraction is defined (declaration-site variance). In Java, however, variance annotations are given by clients when a class abstraction is used (use-site variance).
124124

125-
Scalas tendency towards immutable types makes it that covariant and contravariant types are more common than in other languages, since a mutabable generic type can't be covariant or contravariant.
125+
Scala's tendency towards immutable types makes it that covariant and contravariant types are more common than in other languages, since a mutable generic type must be invariant.

0 commit comments

Comments
 (0)