是什么阻止了静态类型语言有类似Ruby的method_missing的东西?

时间:2010-09-24 15:28:12

标签: ruby scala coldfusion static-typing method-missing

我对静态类型语言没有太多经验(目前正在学习Scala并喜欢它!)但我注意到的一件事是它们似乎没有像Ruby的method_missing或ColdFusion的onMissingMethod那样的东西。静态类型语言是否存在一些固有的限制,可以防止或使其变得困难?

5 个答案:

答案 0 :(得分:21)

当然可以添加一种处理它们的机制,但它与静态类型的不一致:编译时确定您的程序没有类型错误。

<强>附录

Scala 2.9引入了一个实验选项,可以通过这种方式动态处理对类型的访问,否则会导致静态类型检查失败。虽然它仍然由默认禁用功能标志控制,但它在2.10中被改进并变为非实验性的。您可以在SIP 17文档中阅读相关内容。有关Scala 2.10的“模块化”和功能标记的解释,请参阅SIP 18

答案 1 :(得分:2)

Scala版本2.9通过Dynamic特征(scaladoc)引入了此功能。扩展Dynamic的类获得了神奇的方法applyDynamic(methodName, args),类似于Ruby的method_missing。从Scala 2.9开始,必须启用-Xexperimental选项才能使用Dynamic

答案 2 :(得分:1)

在静态类型语言中,直接调用成员函数。如果编译器无法确定要调用的成员函数,则程序将无法编译。从这个意义上讲,方法调用是静态的。

在动态类型语言中,不直接调用成员函数。相反,调用代码会向对象发送消息,然后语言运行时会确定如何处理该消息。例如,运行时将扫描对象以查找具有相同名称的方法,然后将扫描对象以查找名为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();

答案 3 :(得分:1)

仅仅为了进一步发展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 ++一样剥离或内联代码。

答案 4 :(得分:0)

Objective-C有“method_missing”(具体来说,forwardInvocationmethodSignatureForSelector),可以说是静态类型。这样做是因为它会在编译时将静态类型错误视为警告而不是错误,因为方法调度在运行时发生的程度远远大于C ++中的虚拟方法(这就是为什么你可以使用“method_missing”)。 / p>