Livesense Inc.
May 15, 2014
1.5k

# Trait in Scala

2014/05/09 Livesense SICP倶楽部LT大会にて
ScalaのTraitについての解説

May 15, 2014

## Transcript

1. 5SBJUJO4DBMB

-JWFTFOTF4*\$1۞ָ෦-5େձ
ౡ઒༔ଠ

2. 4DBMB

3. CMPHFOGSBODIJTFENJOEDPNTDBMBOPUGVODUJPOBM

4. 4DBMB

5. +BWB

6. w JOUFSGBDFͷσϑΥϧτ࣮૷
w ϥϜμࣜ
w ߴ֊ؔ਺
w ܕਪ࿦ͷڧԽ
w ฒྻੑͷڧԽʢฒྻίϨΫγϣϯɺ\$PNQMFUF'VUVSFʣ
w ஗ԆධՁ
w 4USFBN
w 0QUJPOBM
w FUD IUUQXXXJOGPRDPNKQBSUJDMFTKBWBWTTDBMB
IUUQOFXTNZOBWJKQTQFDJBMKBWB

7. ͦΕͰ΋4DBMB
Λ࢖͍͍͔ͨʁ

8. ͜Μͳࢿྉ࡞Δ͘Β͍
͔ͩΒΘ͔Γ·͢ΑͶʁ

9. ຊ೔ͷςʔϚ
ʰτϨΠτʱ

10. ͳͥτϨΠτΛ
ͱΓ͋͛Δ͔ʁ

11. w τϨΠτ͸4DBMBͷΦϒδΣΫτࢦ޲ݴޠͱ
ͯ͠ͷϋΠϥΠτͷҰͭͩͱࢥ͏ɻ
w "DUPS΍Β'VUVSF΍ΒΛ࢖ͬͨฒߦੑ੍ޚ
ͷར఺͸ଟ͍͚Ͳɺଟ͘ͷ৬ۀϓϩάϥϚ͕
௚໘͢Δ՝୊͸ɺ001Λ࢖ͬͨιϑτ΢ΣΞ
՝୊ͷղܾʹ͋ΔͷͰ͸ͳ͍͔ͱࢥ͏ɻ
w ͱ͍͏͜ͱͰɺ4DBMBͷݴޠ঺հͱͯ͠τϨ
Πτ͔ΒऔΓ্͛ͯΈΔɻ

12. \$ scala
scala> “trait”.translate(“ja_JP”)
res0: List[String] = List(ಛੑ, ಛ௃, ಛ৭)
IUUQFKKFXFCMJPKQDPOUFOUUSBJU

13. τϨΠτͱ͸ʁ

14. ΫϥεͷΑ͏ʹɺϝιουͱϑΟʔ
ϧυͷఆٛΛΧϓηϧԽͨ͠΋ͷ
Ͱɺ4DBMBʹ͓͚Δίʔυ࠶ར
༻ͷجຊ୯ҐʢίοϓຊΑΓʣ

15. trait Philosophical {
def philosophize() {
println(“զࢥ͏ނʹզ͋Γ”)
}
}

16. ΫϥεʹϛοΫεΠϯ
w ந৅ϝϯόʔ͚ͩΛએݴͯ͠ɺϛοΫεΠϯ͢Δ
ΫϥεͰͷ࣮૷Λڧ੍
w ࣮૷Λఆٛ͢Δ͜ͱ΋Ͱ͖Δ
w ෳ਺ͷτϨΠτΛಉ࣌ʹϛοΫεΠϯ͢Δ͜ͱ΋
Ͱ͖Δ
w ϛοΫεΠϯͨ͠ϝιουΛΦʔόʔϥΠυͨ͠
ΓɺTVQFSݺͼग़͢͠Δ͜ͱ΋Ͱ͖Δ

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. TVQFSݺͼग़͠ͷઢܗԽ

21. class Animal
!
trait HasLegs extends Animal
!
trait FourLegged extends HasLegs
!
trait Furry extends Animal
!
class Cat extends Animal
with Furry with FourLegged

22. "OJNBM )BT-FHT
'VSSZ 'PVS-FHHFE
\$BU
DMBTT\$BUFYUFOET"OJNBM
XJUI'VSSZXJUI'PVS-FHHFE
\$BU'PVS-FHHFE
)BT-FHHFE'VSSZ"OJNBM
ઢܗԽ

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
ʰ4DBMBεέʔϥϒϧϓϩάϥϛϯάʱষΑΓ

26. "01ͬΆ͍͜ͱ΋Մೳ
ࢀߟ
IUUQEIBUFOBOFKQKJLP

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. 5SBJU\$ͷΠϯελϯεΛੜ੒͢
Δʹ͸"ͱ#ΛϛοΫεΠϯ͠ͳ
͚Ε͹ͳΒͳ͍ɻ\$͔Β"ͱ#΁
ͷґଘੑΛ໌ࣔ͢Δ͜ͱ͕Ͱ͖Δɻ

31. \$BLF1BUUFSOͰ%*

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. ஫ʣDBLFQBUUFSO
ʹ͍ͭͯ͸໰୊఺΋ࢦఠ
͞Ε͍ͯΔͷͰ஫ҙ

35. IUUQUPHFUUFSDPNMJ

36. ·ͱΊ

37. τϨΠτ࢖͏ͱ001͕ؾ
࣋ͪΑ͘ͳΔɻ͔΋Ͷɻ