はじめに
下記のテキストを通して、基本的な書き方を学びつつ、個人的に気になったことを検証していくメモ代わりです。
https://dwango.github.io/scala_text/basic.html
本当にありがとう、dwango様・・・
トレイト
- ざっくりまとめ
-
extends
,with
でミックスイン - 直接インスタンス化できない(
val traitA = new TraitA
)-
val traitA = new TraitA {}
は無名クラスによる定義なのでインスタンス化ではない
-
- 引数をとれないので、class側で上書きするか、抽象メンバーを持たせることで値を渡す
class ClassA(val name: String) extends TraitA
-
トレイトの基礎
プログラムの分割(モジュール化)と組み立て(合成)は、オブジェクト指向プログラミングでも関数型プログラミングにおいても重要な設計の概念になります。
3つの特徴
- 複数のトレイトを1つのクラスやトレイトにミックスインできる
- 直接インスタンス化できない
- クラスパラメータ(コンストラクタの引数)を取ることができない
複数のトレイトを1つのクラスやトレイトにミックスインできる
-
基本型
scala> :paste // Entering paste mode (ctrl-D to finish) // trait trait TraitA trait TraitB // class class ClassA class ClassB // コンパイルできる class ClassC extends ClassA with TraitA with TraitB // Exiting paste mode, now interpreting. defined trait TraitA defined trait TraitB defined class ClassA defined class ClassB defined class ClassC
-
classをwith句でくくるとエラー(classのミックスインはできない)
scala> :paste // Entering paste mode (ctrl-D to finish) // class class ClassA class ClassB // コンパイルエラー class ClassD extends ClassA with ClassB // Exiting paste mode, now interpreting. <console>:14: error: class ClassB needs to be a trait to be mixed in class ClassD extends ClassA with ClassB ^
直接インスタンス化できない
-
直接インスタンス化してみる
scala> :paste // Entering paste mode (ctrl-D to finish) trait TraitA object ObjectA { val traitA = new TraitA } // Exiting paste mode, now interpreting. <console>:11: error: trait TraitA is abstract; cannot be instantiated val traitA = new TraitA ^
- トレイトが単体で使われることをそもそも想定していないための制限
-
with句のみだとエラー
scala> :paste // Entering paste mode (ctrl-D to finish) trait TraitA class ClassA with TraitA object ObjectA { val classA = new ClassA } // Exiting paste mode, now interpreting. <console>:2: error: ';' expected but 'with' found. class ClassA with TraitA ^
-
基本型
scala> :paste // Entering paste mode (ctrl-D to finish) trait TraitA class ClassA extends TraitA object ObjectA { val classA = new ClassA } // Exiting paste mode, now interpreting. defined trait TraitA defined class ClassA defined module ObjectA
-
new Trait {}
という記法scala> :paste // Entering paste mode (ctrl-D to finish) object ObjectA { val traitA = new Trait{} } // Exiting paste mode, now interpreting. <console>:8: error: not found: type Trait val traitA = new Trait{} ^ --- scala> :paste // Entering paste mode (ctrl-D to finish) object ObjectA { val traitA = new trait {} } // Exiting paste mode, now interpreting. <console>:2: error: identifier expected but 'trait' found. val traitA = new trait {} ^ --- scala> :paste // Entering paste mode (ctrl-D to finish) object ObjectA { val traitA = new trait TraitA{} } // Exiting paste mode, now interpreting. <console>:2: error: identifier expected but 'trait' found. val traitA = new trait TraitA{} ^ --- scala> :paste // Entering paste mode (ctrl-D to finish) trait TraitA object ObjectA { val traitA = new TraitA {} } // Exiting paste mode, now interpreting. defined trait TraitA defined module ObjectA
- Traitを継承した無名のクラスを作ってインスタンスを生成する構文
- トレイトそのものをインスタンス化できているわけではない
クラスパラメータ(コンストラクタの引数)を取ることができない
-
引数をもたせた場合
scala> :paste // Entering paste mode (ctrl-D to finish) class ClassA(val name: String) trait TraitA(val name: String) // Exiting paste mode, now interpreting. <console>:2: error: traits or objects may not have parameters trait TraitA(val name: String) ^
-
抽象メンバーを持たせることで値を渡す
scala> :paste // Entering paste mode (ctrl-D to finish) trait TraitA { var name: String // varであまり良くない定義だが、とりあえず def printName():Unit = println(name) def setName(n: String) = { name = n } } class ClassA extends TraitA object ObjectA { val classA = new ClassA classA.setName("hoge") classA.printName() } // Exiting paste mode, now interpreting. <console>:18: error: class ClassA needs to be abstract, since variable name in trait TraitA of type String is not defined (Note that variables need to be initialized to be defined) class ClassA extends TraitA ^ --- scala> :paste // Entering paste mode (ctrl-D to finish) trait TraitA { var name: String // varであまり良くない定義だが、とりあえず def printName():Unit = println(name) def setName(n: String) = { name = n } } class ClassA(var name: String) extends TraitA object ObjectA { val classA = new ClassA("hoge") def run: Unit = { classA.printName() classA.setName("hogehoge") classA.printName() } } ObjectA.run // Exiting paste mode, now interpreting. hoge hogehoge defined trait TraitA defined class ClassA defined module ObjectA
-
name を上書きするような実装を与える
scala> :paste // Entering paste mode (ctrl-D to finish) trait TraitA { val name: String def printName():Unit = println(name) } object ObjectA { val classA = new TraitA {val name = "hoge"} def run: Unit = { classA.printName() } } ObjectA.run // Exiting paste mode, now interpreting. hoge defined trait TraitA defined module ObjectA --- scala> :paste // Entering paste mode (ctrl-D to finish) trait TraitA { // もし、定義していなかったら? // val name: String def printName():Unit = println(name) } object ObjectA { val classA = new TraitA {val name = "hoge"} def run: Unit = { classA.printName() } } ObjectA.run // Exiting paste mode, now interpreting. <console>:10: error: not found: value name def printName():Unit = println(name) ^