(traitの)defをvalでオーバーライド/実装する

Liftの Loc実装を見ていて気がついた。

scala> trait Hoge {
     |   def fuga:String;
     |   def piyo:String = fuga
     | }
defined trait Hoge

scala> val a = new Hoge {
     |   def fuga = "abc"
     | }
a: java.lang.Object with Hoge = $anon$1@1f2a9da

scala> val b = new Hoge {
     |   val fuga ="zzz"
     | }
b: java.lang.Object with Hoge = $anon$1@1e3bfb6

scala> a.piyo
res3: String = abc

scala> b.piyo
res4: String = zzz

なるほど、こういうことも出来るわけですか。Scala名前空間の仕様、及び、def==val==varみたいな感じの仕様に依っている、のかな?

メソッドpiyoは、そのコンパイル時点では関数としてのfugaしか知らないわけで、そう考えるといろいろ面白いなあ。

ちなみに

def piyo:String = hoge()

はエラーになった。

ちなみに、

scala> trait Hoge {
     |  def fuga():String;
     |   def piyo = fuga()
     | }
defined trait Hoge

scala> val a = new Hoge {
     |   def fuga = "abc"
     | }
a: java.lang.Object with Hoge = $anon$1@14a8f44

scala> a.piyo
res9: String = abc

scala> val b = new Hoge {
     |   val fuga = "zeg"
     | }
b: java.lang.Object with Hoge{def fuga: java.lang.String} = $anon$1@8825a5

scala> b.piyo
res10: String = zeg

でもある。
def hoge():String は コンソールの表示でも "hoge: ()String"みたいな型ででてくるから、これをvalで実装しちゃうってのも出来る。

で、気になったので

class Hoge {
  val a:String = "abc"
}

を scalac して jad して見てみると

 (略)
    public String a()
    {
        return a;
    }
 (略)
    private final String a = "abc";
 (略)

になってた。valへのアクセスはメソッドを通して実施されている。