12

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

4

5 回答 5

21

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

附录

Scala 2.9 引入了一个实验性的选项,可以对类型的访问进行这种动态处理,否则静态类型检查会失败。它在 2.10 中进行了改进并成为非实验性的,尽管它仍然由默认禁用功能标志控制。您可以在SIP 17文档中了解它。有关 Scala 2.10 的“模块化”和功能标志的说明,请参见SIP 18

于 2010-09-24T15:48:10.657 回答
2

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

于 2011-06-25T19:35:51.583 回答
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();
于 2010-09-24T16:01:51.180 回答
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++ 那样剥离或内联代码。

于 2010-09-27T14:29:58.900 回答
0

Objective-C 有“method_missing”(特别是forwardInvocationmethodSignatureForSelector),它可以说是静态类型的。这是有效的,因为它将静态类型错误视为警告而不是编译时的错误,因为方法分派在运行时发生的程度比 C++ 中的虚拟方法之类的要大得多(这就是为什么你可以有“method_missing”的原因)。

于 2010-09-27T14:39:48.787 回答