学んだことをなぐり書き


abstract override

abstract class C {
  def put(x: Int)
  def check() {
    List(10, 20, 30) foreach put
    println(this)
  }
}

class C2 extends C {
  val buf = new scala.collection.mutable.ArrayBuffer[Int]
  def put(x: Int) { buf += x }
  override def toString = buf.toString
}

class CC extends C {
  // 通常abstractのメソッドはsuperで呼ぶことは出来ない
  //def put(x: Int) { super.put(x) } <- error  
  def put(x: Int) {}
}

trait T extends C {
  // traitの場合、他のクラスやトレイトの後でafterメソッドとしてミックスインされる限り、abstractのメソッドをsuperで呼ぶことが出来る。
  // その場合コンパイラに知らせるためにabstract overrideというマークを付けなければならない。
  abstract override def put(x: Int) { super.put(x * 2) }
}

// C2でputが定義されているのでafterメソッドとしてTのputをミックスイン出来る。
class C3 extends C2 with T

trait T2 extends C {
  abstract override def put(x: Int) { super.put(x + 1) }
}

(new C2).check()
(new C3).check()
// newする時にミックスインすることも可能
(new C2 with T2).check()

// 便利なのは複数のトレイトを組み合わせて色々な機能を実現することが可能
// 厳密な規則ではないが、おおむね右に書いたトレイトから先に適応される。
// 下記の場合、1足してから2倍される。
(new C2 with T with T2).check()
ArrayBuffer(10, 20, 30)
ArrayBuffer(20, 40, 60)
ArrayBuffer(11, 21, 31)
ArrayBuffer(22, 42, 62)

メンバーのみ編集できます