自分型アノテーション
自分型アノテーションの用途は二つある。
- thisの別名を定義する。
- クラスの機能を分割する。
thisの別名を定義する
object SelfTypeAnnotationSample1 {
self => // 自分型アノテーション。=>の右側には何もない。「class Internal」を指しているわけでもない。
class Internal {
def procedure = {
SelfTypeAnnotationSample1.this.procedure
self.procedure
}
}
def procedure = {
println("hello world")
}
def main(args: Array[String]) {
new Internal().procedure
}
}この結果は
hello world hello world
クラスの機能を分割する
一つのクラスの機能を複数のクラスに分割する場合、Javaでは一般に集約を行うが(継承はだめ)、Scalaではtraitによるミックスインという方法がある。 しかし、ミックスインでは機能を集約できるものの、その機能が外側から見えてしまう。
他のtraitの機能をターゲットのクラスにミックスインしつつ、そのtraitの存在を外部に教えないようにするために、自分型アノテーションを使うことができる(こういう説明でよいかわからない)。
以下では、SampleはSomeOtherを自分型として指定するが、これは抽象traitである。 Sampleのオブジェクト生成時に実装traitを指定する。
Sampleを使う側は、このオブジェクトがSomeOtherを利用していることは知らないし、そのメソッドにもアクセスすることはできない。
trait SomeOther { def something }
trait SomeOtherImpl extends SomeOther { def something = { println("something") } }
class Sample {
self: SomeOther =>
def test = {
something
}
}
object SelfTypeAnnotationSample2 {
def main(args: Array[String]) {
object SampleImpl extends Sample with SomeOtherImpl;
SampleImpl.test
}
}この手法は「Cakeパターン」と呼ばれるDI手法と言われることがあるのだが、新たなパターンというよりも、「手によるコンストラクタ注入」の代用と言った方がよい。
