我在静态类型语言方面没有太多经验(目前正在学习Scala并喜欢它!),但我注意到一件事情是这些语言似乎从来没有像Ruby的method_missing或ColdFusion的onMissingMethod那样的东西。是不是在静态类型语言中有某种固有限制阻止或使这个实现变得困难呢?
我在静态类型语言方面没有太多经验(目前正在学习Scala并喜欢它!),但我注意到一件事情是这些语言似乎从来没有像Ruby的method_missing或ColdFusion的onMissingMethod那样的东西。是不是在静态类型语言中有某种固有限制阻止或使这个实现变得困难呢?
Scala 2.9版本通过 scaladoc 提供了Dynamic
特质,引入了这个功能。扩展Dynamic
的类会获得神奇的方法applyDynamic(methodName, args)
,它类似于Ruby的method_missing
。从Scala 2.9开始,必须启用-Xexperimental
选项才能使用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();
obj.method(args)
转换为“获取 obj
的 method
成员指向的函数,然后使用 obj
作为第一个参数和 args
调用它”。) - user395760var
与动态类型无关。它会导致编译器从赋给变量的值推断出静态类型。 - Simon Callan进一步回应Randall的帖子,虽然有可能实现,但这违背了静态范式的原因是它超越了“动态分派”。动态分派可以让你愉快地将调用分派到一个动态绑定到已知静态代码的函数。也就是说,编译器设置了从其角度确定性执行的运行时分派。
method_missing
调用的作用是基于方法名称使用switch语句或等效语句(我相信您知道)来决定如何处理“捕获所有”的情况。因此,编译器不知道这里会发生什么。假设编译器做了以下操作:
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旨在成为一种静态安全的语言。
是的,这是可行的,但不符合静态语言的精神。如果您真的想要那种类型的灵活性,多语言编程可能是您的朋友。
注意:Objective-C并非严格静态类型。代码执行的运行时引擎不允许像C/C++那样剥离或内联动态类型系统。
Objective-C有"method_missing"(具体来说,forwardInvocation和methodSignatureForSelector),并且可以说是静态类型的。这是因为它将静态类型错误视为编译时的警告而不是错误,因为方法分派在运行时比C++中的虚拟方法更多(这就是为什么你可以有"method_missing")。
opDispatch
是一个模板方法,在编译时传递方法名和参数类型,因此你可以使用元编程来确定如何“运行”缺失的方法。当然,所有的东西仍然由编译器静态解析。相关SO问题。 - anton.burger