私は静的に型付けされた言語(現在Scalaを学び、それを愛している!)の経験はあまりありませんが、Rubyのmethod_missingやColdFusionのonMissingMethodのようなものがないように見えることに気づきました。静的に型付けされた言語には、これを防止または困難にする固有の制限がありますか?
5 に答える
確かにそれらを処理するメカニズムを追加することはできますが、静的型付けとは相容れません。プログラムに型エラーがないことをコンパイル時に決定します。
補遺
Scala 2.9では、静的型チェックに失敗するような方法で型へのアクセスを動的に処理できるようにする実験的なオプションが導入されました。これは、2.10で改良され、非実験的になりましたが、デフォルトの無効化機能フラグによって制御されています。これについては、 SIP17ドキュメントで読むことができます。Scala 2.10の「モジュール化」と機能フラグの説明については、SIP18を参照してください。
Dynamic
Scalaバージョン2.9は、トレイト(scaladoc )を通じてこの機能を導入しています。拡張するクラスは、Rubyのに類似しDynamic
た魔法のメソッドを取得します。Scala 2.9以降、を使用するにはオプションを有効にする必要があります。applyDynamic(methodName, args)
method_missing
-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();
ランドールの投稿をさらに進めるために、それは可能ですが、それが静的パラダイムに反する理由は、それが「動的ディスパッチ」を超えているからです。動的ディスパッチを使用すると、既知の静的コードに動的にバインドされている関数にディスパッチできます。つまり、コンパイラは、その観点から、実行時に決定論的に実行されるディスパッチを設定します。
呼び出しが行うこと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は静的に安全であることが意図されています言語。
はい、それは実行可能ですが、静的言語の精神ではありません。そのような柔軟性が本当に必要な場合は、polyglotプログラミングがおそらくあなたの友達です。
注:Objective-Cは厳密に静的に型付けされていません。コードが実行されるランタイムエンジンがあり、動的型付けシステムでは、C /C++のようにコードを削除したりインライン化したりすることはできません。
Objective-Cには「method_missing」(具体的には、forwardInvocationとmethodSignatureForSelector)があり、おそらく静的に型付けされています。これが機能するのは、静的タイプのエラーがコンパイル時のエラーではなく警告として扱われるためです。メソッドのディスパッチは、C ++の仮想メソッドのようなものよりもはるかに多く実行時に発生するためです(これが「method_missing」を持つことができる理由です)。