一昨日の記事で紹介したように、
scala-2.9.0.r24111-b20110127020129
を落としてきて、試してみた
追記:やはりなんだか、色々仕様変わってるみたいなので、そのまま残しておきますが以下はあくまで参考程度に。dynamicのソースも2.9.0RC1がでた2011/3/26日時点では、空になって、コンパイラで特殊処理するようになったみたいだし。
そもそもdynamic自体が、コンパイル時にオプションつけないと働かないようになったようです。あと、みずしまさんによるちょっとした説明
2011/1/28日時点でのDynamicのソース↓
package scala /** A trait that supports dynamic invocations. Instances `x` of this trait * allow calls `x.meth(args)` for arbitrary method names `meth` and argument lists * `args`. If a call is not natively supported by `x`, it is rewritten to * `x.invokeDynamic("meth", args)`. */ trait Dynamic { /** The dynamic invocation operation * @param name The name of the invoked method * @param args The arguments to the method */ def invokeDynamic(name: String)(args: Any*): Any /** Returns the underlying value typed as an instance of type T * @param T The target type */ def typed[T]: T }
自分でテスト用に書いたコード↓
object Main{ def main(args:Array[String]){ val a:Int = Test.hoge println(a) val b:Int = Test.fuga println(b) } } object Test extends Dynamic{ def invokeDynamic(name:String)(args:Any*):Int = { name match{ case "hoge" => 1 case _ => 0 } } def typed[T]:T = { null.asInstanceOf[T] } }
色々試した結果、とりあえず上記のコードで、コンパイル通った。
typedっていうMethodをどう定義して使うのかが全くよくわからない(´・ω・`)
で、実行結果は↓
1 0
って感じになります。
逆コンパイルした結果↓
Main$.jad
import scala.Predef$; import scala.ScalaObject; import scala.collection.immutable.Nil$; import scala.runtime.BoxesRunTime; public final class Main$ implements ScalaObject { public void main(String args[]) { int a = Test$.MODULE$.invokeDynamic("hoge", Nil$.MODULE$); Predef$.MODULE$.println(BoxesRunTime.boxToInteger(a)); int b = Test$.MODULE$.invokeDynamic("fuga", Nil$.MODULE$); Predef$.MODULE$.println(BoxesRunTime.boxToInteger(b)); } private Main$() { } public static final Main$ MODULE$ = this; static { new Main$(); } }
Main.jad
public final class Main { public static final void main(String args[]) { Main$.MODULE$.main(args); } }
Test$.jad
import scala.Dynamic; import scala.ScalaObject; import scala.collection.Seq; import scala.runtime.BoxesRunTime; public final class Test$ implements Dynamic, ScalaObject { public int invokeDynamic(String name, Seq args) { String s = name; s; String s1 = "hoge"; if(s != null) goto _L2; else goto _L1 _L1: JVM INSTR pop ; if(s1 == null) goto _L4; else goto _L3 _L2: s1; equals(); JVM INSTR ifeq 32; goto _L4 _L3 _L4: 1; goto _L5 _L3: false; _L5: return; } public Object typed() { Object _tmp = null; return null; } public volatile Object invokeDynamic(String name, Seq args) { return BoxesRunTime.boxToInteger(invokeDynamic(name, args)); } private Test$() { } public static final Test$ MODULE$ = this; static { new Test$(); } }
Test.jad
import scala.collection.Seq; public final class Test { public static final Object typed() { return Test$.MODULE$.typed(); } public static final int invokeDynamic(String s, Seq seq) { return Test$.MODULE$.invokeDynamic(s, seq); } }
なんか使い方ちゃんとわかってないので、あとでまた試す(`・ω・´)
しかも、まだ仕様変わる可能性が大きそうですねぇ
追記:コード例がのってるサイト教えてもらった
@xuwei_k もう解決されてしまったかもしれませんが、こちらが参考になりそうです http://bit.ly/iihLHC
他にもいくつか自分でも見つけたのでメモ
http://stackoverflow.com/questions/4709183/practical-uses-of-a-dynamic-type-in-scala
https://gist.github.com/783618/f741175ffcd8dfe333c2da45cf8fdd4d2b134fdb
http://pastie.org/1468102
http://pastie.org/1469213
さらに追記
そもそも、ネット上にあるコード例みると、
_select_とか
_invoke_ってメソッド定義して使うみたいですね。(Dynamic継承してる場合、この2つの名前のメソッドは、コンパイラに特別扱いされるっていう感じかな?)
しかし、個人的には、なんかこのやり方がダサい・・・というか、このDynamic型自体、IDEなんかのコード補完の対応なんかが微妙になりそうだし、あまり入ってほしくないような・・・