是什么防止静态键入语言具有像Ruby's Method_missing之类的东西?
-
05-10-2019 - |
题
我在静态类型的语言方面没有太多经验(目前正在学习Scala并喜欢它!),但是我注意到的一件事是,他们似乎从来没有像Ruby's Method_missing或Coldfusion的OnmissingMethod这样的东西。静态打字的语言是否有一些固有的限制可以预防或使这一困难?
其他提示
Scala版本2.9通过 Dynamic
特质(斯卡多克)。延伸的类 Dynamic
获取神奇的方法 applyDynamic(methodName, args)
, ,类似于Ruby的 method_missing
. 。从Scala 2.9开始 -Xexperimental
必须启用选项 Dynamic
.
在静态类型的语言中,直接调用成员函数。如果编译器无法确定要调用哪个成员函数,则该程序将不会编译。从这个意义上讲,方法调用是静态的。
在动态键入的语言中,不直接调用成员函数。相反,呼叫代码将消息发送到对象,然后语言运行时算出该消息如何处理。例如,运行时将扫描具有相同名称的方法的对象,然后将对象扫描为具有名称的方法 method_missing
. 。从这个意义上讲,方法调用是动态的。
C#4将静态键入与动态键入结合。变量可能具有编译时类型的 dynamic
. 。该变量上的任何方法的调用都将如动态键入语言一样处理。具有静态类型变量的任何方法调用都将如静态键入语言一样处理。
# static invocation, bound at compile time by the compiler
var s = 6;
s.ToString();
# dynamic invocation, handled at runtime by the CLR
dynamic d = 6;
d.ToString();
只是为了进一步,兰德尔(Randall)的帖子,这是可能的,但是它与静态范式相抵触的原因是它超出了“动态调度”。动态调度愉快地使您可以分配到动态绑定到已知静态代码的函数。即编译器从其角度来确定执行的派遣机构。
什么 method_missing
呼叫确实是“全部捕捉”,您可以在其中根据方法名称使用开关语句或等效的内容来决定要做什么(我敢肯定您知道)。因此,编译器不知道这里会发生什么。假设编译器做了类似的事情:
if (function is known at compile time)
{
provide static call or dynamic call to "some" derivation
}
else
{
bind the function call to obj.method_missing(...) and pass in the "details"
}
那你必须提供 method_missing
像这样:
def method_missing(intendedFunctionName, arguments)
{
if (intendedFunctionName is "X")
{
X may not need arguments, so just do something
}
else if (intendedFunctionName is "Y")
{
Y expects 5 arguments of varying types
Throw exception if there isn't the right number or types
}
... etc ...
}
要求编译器向您发送“任意”(即编译时间不知道)任意类型的参数, intendedFunctionName
您可能不会考虑...好吧,这不是很安全,Scala旨在是一种静态安全的语言。
是的,这是可行的,但不是静态语言的精神。如果您真的想要这种类型的灵活性,那么Polyglot编程可能是您的朋友。
注意:Objective-C并非严格静态键入。有一个运行时引擎执行代码,而动态打字系统不允许像C/C ++那样剥离或嵌入代码。
Objective-C具有“ method_missing”(具体来说, 远期屈服 和 MethodSignatureForselector),可以说是静态输入的。之所以起作用,是因为它会将静态类型错误视为警告,而不是在编译时错误,因为方法调度在运行时发生的时间比C ++中的虚拟方法更大的程度(这就是为什么您可以拥有“ method_missing”)。