継承とかmixinとか。

Scalaには、traitというキーワードがあって、mixin専用のクラスというか、objectを作る事が出来たりするですな。
こいつは、中々に面白い。

object SubTyping extends Application {
    trait Fuga {
        def aaa() = println("Fuga")
        aaa
    }
    trait Hoge {
    	def aaa() = println("Hoge")
        aaa
    }
    trait Moge extends Fuga {
        override def aaa() = println("Moge")
    }
    trait Piro extends Fuga {
        override def aaa() = println("Piro")
    }

    class SubA extends Fuga
    new SubA
    
    class SubB extends Hoge
    new SubB
    
    class SubC extends Moge
    new SubC
    
    class SubD extends Moge with Fuga
    new SubD
    
    class SubE extends Fuga with Moge with Piro
    new SubE
}

まぁ、こんな感じにコードを書く訳。
ちなみに、class宣言でも、メソッド宣言でも無い部分は、コンストラクタ内の処理として実行されるます。
実行結果はこんな感じ

Fuga
Hoge
Moge
Moge
Piro

traitはextendsとwithのどちらを使っても指定出来る感じ。
んで、withだけを使う事は出来ず、継承親が1つだけの時は、traitをextendsしる。


extendsやwithで指定したclassやtraitが同じ名前のメソッドを持ち、それが同じ引数である場合、
そのメソッドは、それぞれのclassやtraitが同一の継承親から継承しoverrideしたメソッドでなければならないみたい。
そうした場合、overrideされたメソッドは、宣言が後ろにある方の処理内容が実行される感じかな。
つまり、ひし形継承問題を顕在化させる様なコードを書くと、後勝ち。となる。
どのクラスのメソッドを継承するか指定する方法があるのかな…。


同じメソッドが、全く違う継承階層の中に現れると、エラーになる。

    class SubF extends Fuga with Hoge
    class SubG extends Hoge with Piro

こんな感じのエラーメッセージ。

   error overriding method aaa in trait Fuga of type ()Unit;
   method aaa in trait Hoge of type ()Unit needs `override' modifier


ちなみに、どんな.classファイルにコンパイルされるのかと言うと、
interface + static メソッドの塊になる。

public interface SubTyping$Fuga
    extends ScalaObject
{

    public abstract void aaa();
}
public abstract class SubTyping$Fuga$class
{

    public static void $init$(SubTyping.Fuga $this)
    {
        $this.aaa();
    }

    public static void aaa(SubTyping.Fuga $this)
    {
        Predef$.MODULE$.println("Fuga");
    }
}
public class SubTyping$SubE
    implements SubTyping$Fuga, SubTyping$Moge, SubTyping$Piro, ScalaObject
{

    public int $tag()
    {
        return scala.ss..tag(this);
    }

    public void aaa()
    {
        aaa.class.aaa(this);
    }

    public SubTyping$SubE()
    {
        aaa.class..init.(this);
        aaa.class..init.(this);
        aaa.class..init.(this);
    }
}

何か微妙にjadが頑張りきれなくて、正確に復元出来ていないけども、
まぁ、その辺は、フォースを感じればいいと思う。

traitがメンバ変数を持ってると、それはそれで結構面白い事になるのだけど、それはいいや。