在Ruby中,当一个类被调用方法未找到时,该类的method_missing(name,*args,&block)方法会被自动调用,通过这个黑科技,人们在ruby上实现了各种元编程技巧. 介绍Dynamic实现了与method_missing几乎一样的功能.然而事实上,它们差别还是挺大的. 先写2个例子吧,分别是scala,ruby实现类似的功能.
import scala.language.dynamics
import scala.io._
object Dispatch extends Dynamic {
def selectDynamic(name:String):String = "Call Method: " + name
def main(args:Array[String]){
println(Dispatch.SCALA);
println(Dispatch.RUBY);
val cls = Dispatch.getClass
while(true){
println(cls.getMethod(StdIn.readLine).invoke(null))
}
}
}
class Dispatch
def method_missing(name,*args,&block)
puts "Call Method: "+name.to_s
end
end
ins = Dispatch.new
ins.SCALA
ins.RUBY
ins.send(gets) while true
都是先尝试调用SCALA和RUBY方法,再循环读取用户输入,调用以输入值为名字的方法. 运行一下~
咦,java.lang.NoSuchMethodException,没有找到方法... 到底是为什么呢?看看scala编译后的字节码把.
[shyling@archlinux:~]$ javap -c Dispatch 16-04-14 15:36
Compiled from "dynamic.scala"
public final class Dispatch {
public static void main(java.lang.String[]);
Code:
0: getstatic #16 // Field Dispatch$.MODULE$:LDispatch$;
3: aload_0
4: invokevirtual #18 // Method Dispatch$.main:([Ljava/lang/String;)V
7: return
public static java.lang.String selectDynamic(java.lang.String);
Code:
0: getstatic #16 // Field Dispatch$.MODULE$:LDispatch$;
3: aload_0
4: invokevirtual #22 // Method Dispatch$.selectDynamic:(Ljava/lang/String;)Ljava/lang/String;
7: areturn
}
[shyling@archlinux:~]$ javap -c Dispatch\$.class 16-04-14 15:36
Compiled from "dynamic.scala"
public final class Dispatch$ implements scala.Dynamic {
public static final Dispatch$ MODULE$;
public static {};
Code:
0: new #2 // class Dispatch$
3: invokespecial #14 // Method "<init>":()V
6: return
public java.lang.String selectDynamic(java.lang.String);
Code:
0: new #18 // class scala/collection/mutable/StringBuilder
3: dup
4: invokespecial #19 // Method scala/collection/mutable/StringBuilder."<init>":()V
7: ldc #21 // String Call Method:
9: invokevirtual #25 // Method scala/collection/mutable/StringBuilder.append:(Ljava/lang/Object;)Lscala/collection/mutable/StringBuilder;
12: aload_1
13: invokevirtual #25 // Method scala/collection/mutable/StringBuilder.append:(Ljava/lang/Object;)Lscala/collection/mutable/StringBuilder;
16: invokevirtual #29 // Method scala/collection/mutable/StringBuilder.toString:()Ljava/lang/String;
19: areturn
public void main(java.lang.String[]);
Code:
0: getstatic #39 // Field scala/Predef$.MODULE$:Lscala/Predef$;
3: aload_0
4: ldc #41 // String SCALA
6: invokevirtual #43 // Method selectDynamic:(Ljava/lang/String;)Ljava/lang/String;
9: invokevirtual #47 // Method scala/Predef$.println:(Ljava/lang/Object;)V
12: getstatic #39 // Field scala/Predef$.MODULE$:Lscala/Predef$;
15: aload_0
16: ldc #49 // String RUBY
18: invokevirtual #43 // Method selectDynamic:(Ljava/lang/String;)Ljava/lang/String;
21: invokevirtual #47 // Method scala/Predef$.println:(Ljava/lang/Object;)V
24: aload_0
25: invokevirtual #53 // Method java/lang/Object.getClass:()Ljava/lang/Class;
28: astore_2
29: getstatic #39 // Field scala/Predef$.MODULE$:Lscala/Predef$;
32: aload_2
33: getstatic #58 // Field scala/io/StdIn$.MODULE$:Lscala/io/StdIn$;
36: invokevirtual #61 // Method scala/io/StdIn$.readLine:()Ljava/lang/String;
39: iconst_0
40: anewarray #63 // class java/lang/Class
43: invokevirtual #67 // Method java/lang/Class.getMethod:(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;
46: aconst_null
47: iconst_0
48: anewarray #4 // class java/lang/Object
51: invokevirtual #73 // Method java/lang/reflect/Method.invoke:(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;
54: invokevirtual #47 // Method scala/Predef$.println:(Ljava/lang/Object;)V
57: goto 29
}
可以看到Dispatch.SCALA仅仅是被编译器翻译成了Dispatch.selectDynamic("SCALA"),其他的并没有什么黑科技.因为jvm本身没有提供类似method_missing的方法,所以...通过反射调用不存在的方法时,会抛出NoSuchMethodException. 假如我们想在jvm更贴近实现method_missing需要怎么做呢?
好像没有特别好的办法.
感觉都不如method_missing优雅啊.动态语言的优势么2333 (责任编辑:最模板) |



Universal 英文综合类商城
人气:271
ecshop仿西米零食网模板
人气:1041
黑色衣服鞋子外贸商城|
人气:755
仿万家购物|百家和等返利
人气:13497
ecshop网易保健品绿色商城
人气:417
ecshop英文数码模板
人气:575