Publicité
Publicité

Contenu connexe

Publicité

Dernier(20)

Publicité

Trait in scala

  1. Trait in Scala 2014/05/08 Livesense SICP読書会LT大会
  2. Scala
  3. blog.enfranchisedmind.com/2009/05/scala-not-functional/
  4. Scala
  5. Java8
  6. • interfaceのデフォルト実装 • ラムダ式 • 高階関数 • 型推論の強化 • 並列性の強化(並列コレクション、CompleteFuture) • 遅延評価 • Stream • Optional • etc http://www.infoq.com/jp/articles/java-8-vs-scala http://news.mynavi.jp/special/2014/java8/
  7. それでもScala を使いたいか?
  8. こんな資料作るくらい だからわかりますよね?
  9. 本日のテーマ 『トレイト』
  10. なぜトレイトを とりあげるか?
  11. • トレイトはScalaのオブジェクト指向言語と してのハイライトの一つだと思う。 • ActorやらFutureやらを使った並行性制御 の利点は多いけど、多くの職業プログラマが 直面する課題は、OOPを使ったソフトウェア 課題の解決にあるのではないかと思う。 • ということで、Scalaの言語紹介としてトレ イトから取り上げてみる。
  12. $ scala scala> “trait”.translate(“ja_JP”) res0: List[String] = List(特性, 特徴, 特色) http://ejje.weblio.jp/content/trait
  13. トレイトとは?
  14. クラスのように、メソッドとフィー ルドの定義をカプセル化したもの で、Scalaにおけるコード再利 用の基本単位(コップ本より)
  15. trait Philosophical { def philosophize() { println(“我思う故に我あり”) } }
  16. クラスにミックスイン • 抽象メンバーだけを宣言して、ミックスインする クラスでの実装を強制 • 実装を定義することもできる • 複数のトレイトを同時にミックスインすることも できる • ミックスインしたメソッドをオーバーライドした り、super呼び出しすることもできる
  17. 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") } }
  18. インスタンス生成時に ミックスイン
  19. class Japanese ! trait Kansai ! trait Kanto ! val me = new Japanese with Kansai with Kanto
  20. super呼び出しの線形化
  21. class Animal ! trait HasLegs extends Animal ! trait FourLegged extends HasLegs ! trait Furry extends Animal ! class Cat extends Animal with Furry with FourLegged
  22. Animal HasLegs Furry FourLegged Cat class Cat extends Animal with Furry with FourLegged Cat -> FourLegged -> HasLegged -> Furry -> Animal 線形化
  23. 積み重ね可能な変更
  24. abstract class IntQueue { def put(x: Int) def get(): Int } ! import scala.collection.mutable.ArrayBuffer class 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) } }
  25. val q1 = new BasicIntQueue q1.put(10) q1.get() // Int = 10 ! val q2 = new BasicIntQueue with Doubling q2.put(10) q2.get() // Int = 20 ! val q3 = new BasicIntQueue with Doubling with Filtering q3.put(-10) q3.get() // Int = 20 『Scalaスケーラブルプログラミング』12章より
  26. AOPっぽいことも可能 参考) http://d.hatena.ne.jp/j5ik2o/20101103/1288752727
  27. 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 LoggableExecutor e.execute
  28. 自分型アノテーション
  29. 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 B c.f // String = foobar
  30. Trait Cのインスタンスを生成す るにはAとBをミックスインしな ければならない。CからAとBへ の依存性を明示することができる。
  31. Cake PatternでDI
  32. 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) } }
  33. 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)
  34. 注)cake pattern については問題点も指摘 されているので注意
  35. http://togetter.com/li/539827
  36. まとめ
  37. トレイト使うとOOPが気 持ちよくなる。かもね。
Publicité