Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add code tabs for _tour/compound-types #2552

Merged
merged 8 commits into from
Sep 27, 2022
Merged
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 45 additions & 5 deletions _tour/compound-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ Sometimes it is necessary to express that the type of an object is a subtype of

Suppose we have two traits `Cloneable` and `Resetable`:

{% tabs compound-types_1 class=tabs-scala-version %}
{% tab 'Scala 2' for=compound-types_1 %}
```scala mdoc
trait Cloneable extends java.lang.Cloneable {
override def clone(): Cloneable = {
Expand All @@ -24,28 +26,66 @@ trait Resetable {
def reset: Unit
}
```
{% endtab %}
{% tab 'Scala 3' for=compound-types_1 %}
```scala
trait Cloneable extends java.lang.Cloneable:
override def clone(): Cloneable =
super.clone().asInstanceOf[Cloneable]
trait Resetable:
def reset: Unit
```
{% endtab %}
{% endtabs %}

Now suppose we want to write a function `cloneAndReset` which takes an object, clones it and resets the original object:

```
{% tabs compound-types_2 class=tabs-scala-version %}
{% tab 'Scala 2' for=compound-types_2 %}
```scala mdoc:fail
def cloneAndReset(obj: ?): Cloneable = {
val cloned = obj.clone()
obj.reset
cloned
}
```
{% endtab %}
{% tab 'Scala 3' for=compound-types_2 %}
```scala
def cloneAndReset(obj: ?): Cloneable =
val cloned = obj.clone()
obj.reset
cloned
```
{% endtab %}
{% endtabs %}

The question arises what the type of the parameter `obj` is. If it's `Cloneable` then the object can be `clone`d, but not `reset`; if it's `Resetable` we can `reset` it, but there is no `clone` operation. To avoid type casts in such a situation, we can specify the type of `obj` to be both `Cloneable` and `Resetable`. This compound type is written like this in Scala: `Cloneable with Resetable`.
The question arises what the type of the parameter `obj` is. If it's `Cloneable` then the object can be `clone`d, but not `reset`; if it's `Resetable` we can `reset` it, but there is no `clone` operation. To avoid type casts in such a situation, we can specify the type of `obj` to be both `Cloneable` and `Resetable`.
{% tabs compound-types_3 class=tabs-scala-version %}
{% tab 'Scala 2' for=compound-types_3 %}
This compound type is written like this in Scala: `Cloneable with Resetable`.

Here's the updated function:

```
```scala mdoc:fail
def cloneAndReset(obj: Cloneable with Resetable): Cloneable = {
//...
}
```

Compound types can consist of several object types and they may have a single refinement which can be used to narrow the signature of existing object members.
The general form is: `A with B with C ... { refinement }`
flomebul marked this conversation as resolved.
Show resolved Hide resolved
{% endtab %}
{% tab 'Scala 3' for=compound-types_3 %}
This compound type is written like this in Scala: `Cloneable & Resetable`.

Here's the updated function:
```scala
def cloneAndReset(obj: Cloneable & Resetable): Cloneable = {
//...
}
```
Compound types can consist of several object types and they may have a single refinement which can be used to narrow the signature of existing object members.
The general form is: `A & B & C ... { refinement }`
flomebul marked this conversation as resolved.
Show resolved Hide resolved
{% endtab %}
{% endtabs %}

An example for the use of refinements is given on the page about [class composition with mixins](mixin-class-composition.html).