Skip to content

Commit d9fa877

Browse files
bishaboshasjrd
authored andcommitted
apply other-new-features/trait-parameters.md
1 parent 51bbee0 commit d9fa877

File tree

3 files changed

+110
-94
lines changed

3 files changed

+110
-94
lines changed

docs/_spec/05-classes-and-objects.md

Lines changed: 76 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,10 @@ If this is not a template of a trait, then its _evaluation_ consists of the foll
9292

9393
- First, the superclass constructor ´sc´ is
9494
[evaluated](#constructor-invocations).
95-
- Then, all base classes in the template's [linearization](#class-linearization) up to the template's superclass denoted by ´sc´ are mixin-evaluated.
96-
Mixin-evaluation happens in reverse order of occurrence in the linearization.
95+
- Then, all base classes in the template's [linearization](#class-linearization) up to the template's superclass denoted by ´sc´ are evaluated.
96+
evaluation happens in reverse order of occurrence in the linearization. Each evaluation occurs as follows:
97+
- First, arguments to ´mt_i´ are evaluated from left to right, and set as parameters of ´mt_i´.
98+
- ´mt_i´ is then mixin-evaluated.
9799
- Finally, the statement sequence ´\mathit{stats}\,´ is evaluated.
98100

99101
### Constructor Invocations
@@ -662,13 +664,10 @@ This form of extensibility can be excluded by declaring the base class `Expr` `s
662664
## Traits
663665

664666
```ebnf
665-
TmplDef ::= ‘trait’ TraitDef
666-
TraitDef ::= id [TypeParamClause] TraitTemplateOpt
667-
TraitTemplateOpt ::= ‘extends’ TraitTemplate | [[‘extends’] TemplateBody]
667+
TmplDef ::= ‘trait’ ClassDef
668668
```
669669

670670
A _trait_ is a class that is meant to be added to some other class as a mixin.
671-
Unlike normal classes, traits cannot have constructor parameters.
672671
Furthermore, no constructor arguments are passed to the superclass of the trait.
673672
This is not necessary as traits are initialized after the superclass is initialized.
674673

@@ -743,9 +742,80 @@ object MyTable extends ListTable[String, Int](0) with SynchronizedTable[String,
743742
The object `MyTable` inherits its `get` and `set` method from `SynchronizedTable`.
744743
The `super` calls in these methods are re-bound to refer to the corresponding implementations in `ListTable`, which is the actual supertype of `SynchronizedTable` in `MyTable`.
745744

745+
### Extending parameterized traits
746+
747+
Extra rules apply for extending a trait with parameters:
748+
749+
1. If a class `´C´` extends a parameterized trait `´T´`, and its superclass does not, `´C´` _must_ pass arguments to `´T´`.
750+
751+
2. If a class `´C´` extends a parameterized trait `´T´`, and its superclass does as well, `´C´` _must not_ pass arguments to `´T´`.
752+
753+
3. Traits must never pass arguments to parent traits.
754+
755+
4. If a class `´C´` extends an unparameterized trait `´T_i´` and the base types of `´T_i´` include parameterized trait `´T_j´`, and the superclass of `´C´` does not extend `´T_j´`, then `´C´` _must_ also explicitly extend `´T_j´` and pass arguments.
756+
This rule is relaxed if the missing trait contains only context parameters. In that case the trait reference is implicitly inserted as an additional parent with inferred arguments.
757+
758+
###### Example - Preventing ambiguities
759+
760+
The following listing tries to extend `Greeting` twice, with different parameters.
761+
762+
```scala
763+
trait Greeting(val name: String):
764+
def msg = s"How are you, $name"
765+
766+
class C extends Greeting("Bob")
767+
768+
class D extends C, Greeting("Bill") // error
769+
770+
@main def greet = println(D().msg)
771+
```
772+
773+
Should this program print "Bob" or "Bill"? In fact this program is illegal, because it violates rule 2 above.
774+
Instead, `D` can extend `Greeting` without passing arguments.
775+
776+
###### Example - Overriding
777+
778+
Here's a variant of `Greeting` that overrides `msg`:
779+
```scala
780+
trait FormalGreeting extends Greeting:
781+
override def msg = s"How do you do, $name"
782+
```
783+
784+
Due to rule 4, the following class extending `FormalGreeting` is required to also extend `Greeting` with arguments:
785+
```scala
786+
class GreetBobFormally extends FormalGreeting, Greeting("Bob")
787+
```
788+
789+
###### Example - Inferred context parameters
790+
791+
Here's a variant of `Greeting` where the addressee is a context parameter of type `ImpliedName`:
792+
793+
```scala
794+
trait ImpliedGreeting(using val iname: ImpliedName):
795+
def msg = s"How are you, $iname"
796+
797+
case class ImpliedName(name: String):
798+
override def toString = name
799+
800+
trait ImpliedFormalGreeting extends ImpliedGreeting:
801+
override def msg = s"How do you do, $iname"
802+
803+
class F(using iname: ImpliedName) extends ImpliedFormalGreeting
804+
```
805+
806+
The definition of `F` in the last line is implicitly expanded to
807+
```scala
808+
class F(using iname: ImpliedName) extends
809+
Object, // implicitly inserted
810+
ImpliedGreeting(using iname), // implicitly inserted
811+
ImpliedFormalGreeting
812+
```
813+
Due to rule 4, `F` is required to also extend `ImpliedGreeting` and pass arguments to it, however note that because `ImpliedGreeting` has only context parameters the extension was added implicitly.
814+
746815
## Object Definitions
747816

748817
```ebnf
818+
TmplDef ::= ‘object’ ObjectDef
749819
ObjectDef ::= id ClassTemplate
750820
```
751821

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
---
2+
layout: doc-page
3+
title: "Trait Parameters"
4+
nightlyOf: https://docs.scala-lang.org/scala3/reference/other-new-features/trait-parameters.html
5+
---
6+
7+
Scala 3 enables traits to have parameters, just like a class.
8+
9+
For example, here is a trait `Greeting`:
10+
```scala
11+
trait Greeting(val name: String):
12+
def msg = s"How are you, $name"
13+
```
14+
15+
A class, enum, or object can extend `Greeting` as follows:
16+
17+
```scala
18+
class Greet extends Greeting("Bob"):
19+
println(msg)
20+
```
21+
22+
However if another trait extends `Greeting` then it must not pass arguments:
23+
24+
```scala
25+
trait FormalGreeting extends Greeting:
26+
override def msg = s"How do you do, $name"
27+
```
28+
29+
If you want a class to greet Bob formally, then you should extend both `FormalGreeting` and `Greeting`:
30+
31+
```scala
32+
class GreetFormally extends FormalGreeting, Greeting("Bob"):
33+
println(msg)
34+
```

docs/_spec/TODOreference/other-new-features/trait-parameters.md

Lines changed: 0 additions & 88 deletions
This file was deleted.

0 commit comments

Comments
 (0)