37
Trait in Scala 2014/05/08 Livesense SICP読書会LT大会

Trait in scala

Embed Size (px)

DESCRIPTION

社内のLT大会でScalaについてお話するということで、Scalaのオブジェクト指向要素の中核であるところのTraitについて。

Citation preview

Page 1: Trait in scala

Trait in Scala

2014/05/08 Livesense SICP読書会LT大会

Page 2: Trait in scala

Scala

Page 4: Trait in scala

Scala

Page 5: Trait in scala

Java8

Page 6: Trait in scala

• interfaceのデフォルト実装

• ラムダ式

• 高階関数

• 型推論の強化

• 並列性の強化(並列コレクション、CompleteFuture)

• 遅延評価

• Stream

• Optional

• etc http://www.infoq.com/jp/articles/java-8-vs-scalahttp://news.mynavi.jp/special/2014/java8/

Page 7: Trait in scala

それでもScala を使いたいか?

Page 8: Trait in scala

こんな資料作るくらいだからわかりますよね?

Page 9: Trait in scala

本日のテーマ 『トレイト』

Page 10: Trait in scala

なぜトレイトを とりあげるか?

Page 11: Trait in scala

• トレイトはScalaのオブジェクト指向言語としてのハイライトの一つだと思う。

• ActorやらFutureやらを使った並行性制御の利点は多いけど、多くの職業プログラマが直面する課題は、OOPを使ったソフトウェア課題の解決にあるのではないかと思う。

• ということで、Scalaの言語紹介としてトレイトから取り上げてみる。

Page 12: Trait in scala

$ scalascala> “trait”.translate(“ja_JP”)res0: List[String] = List(特性, 特徴, 特色)

http://ejje.weblio.jp/content/trait

Page 13: Trait in scala

トレイトとは?

Page 14: Trait in scala

クラスのように、メソッドとフィールドの定義をカプセル化したもので、Scalaにおけるコード再利用の基本単位(コップ本より)

Page 15: Trait in scala

trait Philosophical { def philosophize() { println(“我思う故に我あり”) }}

Page 16: Trait in scala

クラスにミックスイン• 抽象メンバーだけを宣言して、ミックスインするクラスでの実装を強制

• 実装を定義することもできる

• 複数のトレイトを同時にミックスインすることもできる

• ミックスインしたメソッドをオーバーライドしたり、super呼び出しすることもできる

Page 17: Trait in scala

trait A { def f() // 抽象メソッド}!trait B { def foo() = println("foo")}!trait C { def bar() = println("bar")}!class D extends A with B with C { def f() = foo() // 抽象メソッドを実装&トレイトBのfooを呼び出し override def bar() = { // トレイトCのbarメソッドをoverride super.bar() // トレイトCのbarメソッドを呼び出し println("BAR") }}

Page 18: Trait in scala

インスタンス生成時に ミックスイン

Page 19: Trait in scala

class Japanese!

trait Kansai!

trait Kanto!

val me = new Japanese with Kansai with Kanto

Page 20: Trait in scala

super呼び出しの線形化

Page 21: Trait in scala

class Animal!

trait HasLegs extends Animal!

trait FourLegged extends HasLegs!

trait Furry extends Animal!

class Cat extends Animal with Furry with FourLegged

Page 22: Trait in scala

Animal HasLegs

Furry FourLegged

Cat

class Cat extends Animal with Furry with FourLegged

Cat -> FourLegged -> HasLegged -> Furry -> Animal with Furry with FourLegged

線形化

Page 23: Trait in scala

積み重ね可能な変更

Page 24: Trait in scala

abstract class IntQueue { def put(x: Int) def get(): Int}!import scala.collection.mutable.ArrayBufferclass BasicIntQueue { private val but = new ArrayBuffer[Int] def put(x: Int) = but += x def get() = but.remove(0)}!trait Doubling extends IntQueue { abstract override def put(x: Int) = { super.put(2 * x) }}!trait Filtering extends IntQueue { abstract override def put(x: Int) = { super.put(x.abs) }}

Page 25: Trait in scala

val q1 = new BasicIntQueueq1.put(10)q1.get() // Int = 10!

val q2 = new BasicIntQueue with Doublingq2.put(10)q2.get() // Int = 20!

val q3 = new BasicIntQueue with Doubling with Filteringq3.put(-10)q3.get() // Int = 20

『Scalaスケーラブルプログラミング』12章より

Page 26: Trait in scala

AOPっぽいことも可能

参考) http://d.hatena.ne.jp/j5ik2o/20101103/1288752727

Page 27: Trait in scala

trait Executor { def execute(): Unit}!trait LoggableExecutor extends Executor { def log(() => Unit):Unit = … abstract override def execute(): Unit { log { super.execute } }}!class SomeExecutor extends Executor { def execute(): Unit = …}!val e = new SomeExecutor with LoggableExecutore.execute

Page 28: Trait in scala

自分型アノテーション

Page 29: Trait in scala

trait A { def foo() = “foo”}!

trait B { def bar() = “bar”}!

trait C { this: A with B => def f() = foo + bar}!

val c = new C with A with Bc.f // String = foobar

Page 30: Trait in scala

Trait Cのインスタンスを生成するにはAとBをミックスインしなければならない。CからAとBへの依存性を明示することができる。

Page 31: Trait in scala

Cake PatternでDI

Page 32: Trait in scala

class User!trait UserRepositoryComponent { val repos: UserRepository trait UserRepository { def findById(id: Int): User }}!class UserService { this: UserRepositoryComponent => def findById(id: Int): User = { repos.findById(id) }}

Page 33: Trait in scala

trait MySQLUserRepositoryComponent extends UserRepository Component { val repos = new MySQLUserRepository class MySQLUserRepository = { def findById(id: Int): User = … }}!val userService = new UserService with MySQLUserRepositoryComponent!val user = userService.findById(1)

Page 34: Trait in scala

注)cake pattern については問題点も指摘されているので注意

Page 35: Trait in scala

http://togetter.com/li/539827

Page 36: Trait in scala

まとめ

Page 37: Trait in scala

トレイト使うとOOPが気持ちよくなる。かもね。