Upload page content

You can upload content for the page named below. If you change the page name, you can also upload content for another page. If the page name is empty, we derive the page name from the file name.

File to load page content from
Page name
Comment

Locked History Actions

scala/selfTypeAnnotation

自分型アノテーション

自分型アノテーションの用途は二つある。

  • 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手法と言われることがあるのだが、新たなパターンというよりも、「手によるコンストラクタ注入」の代用と言った方がよい。