Scalaのtraitを試す

2008/06/07 22:57

※ 商品のリンクをクリックして何かを購入すると私に少額の報酬が入ることがあります【広告表示】

さて、Python温泉ではScalaで動作するLIFTを見てみようと思っていますが、その前にScalaについてもう少し。

このエントリは、OSX(10.5.3)上のScala version 2.7.1.final (Java HotSpot(TM) Client VM, Java 1.5.0_13)を前提としています。core2duoのマシンが欲しいなぁ…

Scala勉強会で気になった機能にtraitという機能があります。 traitはclassに対して機能を追加するような使い方をするもので、定義自体はclassに似ています。

Javaは多重継承を禁じていますので、共通機能を複数持ったクラスを作ろうと思うとclassの継承とinterfaceの実装を組み合わせなければなりません。

interface自体は実装を持たないため、同じ名前のメソッドを実装していることを保証するに過ぎないもので、しかも何度も同じような実装を記述しなければなりませんでした。 こんなこと をしようとするとJavaは助長なコードを書かざるを得なかったのです。

traitを使えば、機能の追加はこんな感じに書けます。AnyRefという参照型のボスを継承していますが、ここに本来継承したいクラスがくると考えてください。

バラバラの機能 BehaviorA と BehaviorB を trait として定義しています。

このscalaコードをコンパイルし、scala Testと実行すると、以下のように出力します。

実装を持った BehaviorA と BehaviorB の機能を使えるMyClassが出来上がりました。

でも、ちょっと待ってください。Scalaって実はJavaのバイトコードにコンパイルされるんですよ。Javaって多重継承できませんよね?

できあがったclassファイルをjadでデコンパイルしてみました。 デコンパイルされたコードを見て、まず、へぇー、と。なんというかいいですねw

ちなみに、traitは状態も持てます。また「同名のメソッド等を知らないうちに上書きしてしまうのでは?」という恐れに対しては、メソッド等の上書き時にはきちんとoverride宣言をしないとコンパイルエラーとなるといった細やかな気の使い方で、安全にtraitを使用できるようになっています。

以下、デコンパイルしたコード

BehaviorA.jad

  import scala.ScalaObject;

  public interface BehaviorA
      extends ScalaObject
  {

      public abstract String hello(String s);
  }
BehaviorA$class.jad

  import scala.StringBuilder;

  public abstract class BehaviorA$class
  {

              public static void $init$(BehaviorA
              behaviora)
              {
              }

              public static String hello(BehaviorA $this,
              String name)
              {
  /*   2*/        return (new StringBuilder()).append("BehaviorA::hello
  (").append(name).append(")").toString();
              }
  }
BehaviorB.jad

  import scala.ScalaObject;

  public interface BehaviorB
      extends ScalaObject
  {

      public abstract String gooby(String s);
  }
BehaviorB$class.jad

  import scala.StringBuilder;

  public abstract class BehaviorB$class
  {

              public static void $init$(BehaviorB
              behaviorb)
              {
              }

              public static String gooby(BehaviorB $this,
              String name)
              {
  /*   6*/        return (new StringBuilder()).append("BehaviorB::gooby
  (").append(name).append(")").toString();
              }
  }
MainClass.jad

  import scala.ScalaObject;
  import scala.StringBuilder;

  public class MainClass
      implements BehaviorA, BehaviorB, ScalaObject
  {

              public MainClass()
              {
  /*   9*/        BehaviorA.class.$init$(this);
  /*   9*/        BehaviorB.class.$init$(this);
              }

              public String test()
              {
  /*  11*/        return (new
  StringBuilder()).append(hello(getClass().getName())).append(" and
  ").append(gooby(getClass().getName())).toString();
              }

              public int $tag()
              {
  /*   9*/        return scala.ScalaObject.class.$tag(this);
              }

              public String hello(String x$1)
              {
  /*   9*/        return BehaviorA.class.hello(this, x$1);
              }

              public String gooby(String x$1)
              {
  /*   9*/        return BehaviorB.class.gooby(this, x$1);
              }
  }
Test$.jad

  import scala.Predef$;
  import scala.ScalaObject;

  public final class Test$
      implements ScalaObject
  {

              public Test$()
              {
              }

              public void main(String args[])
              {
  /*  17*/        MainClass mc = new MainClass();
  /*  18*/        Predef$.MODULE$.println(mc.test());
              }

              public int $tag()
              {
  /*  15*/        return scala.ScalaObject.class.$tag(this);
              }

              public static final Test$ MODULE$ = this;

              static
              {
                  new Test$();
              }
  }
Test.jad

  public final class Test
  {

      public static final int $tag()
      {
          return Test$.MODULE$.$tag();
      }

      public static final void main(String args[])
      {
          Test$.MODULE$.main(args);
      }
  }

Prev Entry

Next Entry