現代言語の場合、それは単なる構文糖です。完全に言語に依存しない方法で、それ以上のものです。
以前は、この答えは単に構文の砂糖以上のものであると述べていましたが、コメントでわかるように、Falcoは現代の言語がすべて欠落しているように見えるパズルが1つあると指摘しました。メソッドのオーバーロードと、同じステップで呼び出す関数の動的な決定を混在させません。これは後で明らかにされます。
これがもっとあるべき理由です。
メソッドのオーバーロードと型なし変数の両方をサポートする言語を検討してください。次のメソッドプロトタイプを使用できます。
bool someFunction(int arg);
bool someFunction(string arg);
いくつかの言語では、コンパイル時にこれらのどれがコードの特定の行によって呼び出されるかを知ることにおそらく辞任するでしょう。ただし、一部の言語では、すべての変数が型付けされているわけではない(またはすべて暗黙的に型付けされObject
ている)
dict roomNumber; // some hotels use numbers, some use letters, and some use
// alphanumerical strings. In some languages, built-in dictionary
// types automatically use untyped values for their keys to map to,
// so it makes more sense then to allow for both ints and strings in
// your code.
それでは、someFunction
これらの部屋番号の1つに適用する場合はどうでしょうか。あなたはこれを呼ぶ:
someFunction(roomNumber[someSortOfKey]);
されるsomeFunction(int)
と呼ばれる、またはされるsomeFunction(string)
と呼ばれますか?ここでは、特に高レベル言語で、これらが完全に直交する方法ではない1つの例を示します。言語は-実行時に-これらのうちのどれを呼び出すかを把握する必要があるため、これらは少なくともこれらと少なくとも同じメソッドであると見なす必要があります。
単純にテンプレートを使用しないのはなぜですか?型付けされていない引数を使用しないのはなぜですか?
柔軟性ときめ細かな制御。テンプレート/型指定されていない引数を使用する方が適切な場合もありますが、そうでない場合もあります。
たとえば、それぞれが引数としてint
aとa string
をとる2つのメソッドシグネチャを持っているが、シグネチャごとに順序が異なる場合について考える必要があります。各署名の実装はほとんど同じことを行うことができますが、わずかに異なるひねりを加えているため、これを行う正当な理由があります。たとえば、ロギングが異なる場合があります。または、まったく同じことをしても、引数が指定された順序から特定の情報を自動的に収集できる場合があります。技術的には、擬似スイッチステートメントを使用して、渡された各引数のタイプを判別することもできますが、それは面倒です。
それでは、この次の例は悪いプログラミングの習慣ですか?
bool stringIsTrue(int arg)
{
if (arg.toString() == "0")
{
return false;
}
else
{
return true;
}
}
bool stringIsTrue(Object arg)
{
if (arg.toString() == "0")
{
return false;
}
else
{
return true;
}
}
bool stringIsTrue(string arg)
{
if (arg == "0")
{
return false;
}
else
{
return true;
}
}
はい、全般的に。この特定の例では、誰かがこれを特定のプリミティブ型に適用しようとするのを防ぎ、予期しない動作を取り戻すことができます(これは良いことです)。ただし、上記のコードを省略し、実際には、すべてのプリミティブ型とObject
sのオーバーロードがあると仮定しましょう。次に、次のコードが実際により適切です。
bool stringIsTrue(untyped arg)
{
if (arg.toString() == "0")
{
return false;
}
else
{
return true;
}
}
しかし、これをint
sとstring
sにのみ使用する必要がある場合、およびそれに応じてより単純またはより複雑な条件に基づいてtrueを返すようにしたい場合はどうでしょうか。次に、オーバーロードを使用する正当な理由があります。
bool appearsToBeFirstFloor(int arg)
{
if (arg.digitAt(0) == 1)
{
return true;
}
else
{
return false;
}
}
bool appearsToBeFirstFloor(string arg)
{
string firstCharacter = arg.characterAt(0);
if (firstCharacter.isDigit())
{
return appearsToBeFirstFloor(int(firstCharacter));
}
else if (firstCharacter.toUpper() == "A")
{
return true;
}
else
{
return false;
}
}
しかし、これらの関数に2つの異なる名前を付けるだけではどうでしょうか。あなたにはまだ同じ量のきめ細かな制御がありますよね?
前に述べたように、一部のホテルでは数字を使用し、一部のホテルでは文字を使用し、一部のホテルでは数字と文字を組み合わせて使用しているためです。
appearsToBeFirstFloor(roomNumber[someSortOfKey]);
// will treat ints and strings differently, without you having to write extra code
// every single spot where the function is being called
これは、実際に私が実際に使用するのとまったく同じコードではありませんが、私がうまく行っている点を説明する必要があります。
しかし...これが、現代の言語の構文糖に過ぎない理由です。
Falcoは、現在の言語は基本的にメソッドのオーバーロードと動的な機能選択を同じステップ内で混在させないというコメントの中でポイントを上げました。以前に特定の言語が機能することを理解していた方法appearsToBeFirstFloor
は、上記の例でオーバーロードでき、言語は実行時に型指定されていない変数のランタイム値に応じて、呼び出される関数のバージョンを決定することでした。この混乱は、ActionScript 3.0のようなECMA類の言語での作業に一部起因します。ActionScript3.0では、実行時に特定のコード行で呼び出される関数を簡単にランダム化できます。
ご存知かもしれませんが、ActionScript 3はメソッドのオーバーロードをサポートしていません。VB.NETの場合、型を明示的に割り当てることなく変数を宣言および設定できますが、これらの変数をオーバーロードメソッドに引数として渡そうとすると、ランタイム値を読み取って呼び出すメソッドを決定する必要がありません。代わりに、型の引数を持つ型、Object
または型のないメソッド、またはそのような何かを見つけたいと思っています。そうint
対のstring
例上記のいずれか、その言語では動作しないでしょう。C ++にも同様の問題があります。ボイドポインターなどのメカニズムを使用する場合、コンパイル時に型を手動で明確にする必要があるためです。
最初のヘッダーにあるように...
現代言語の場合、それは単なる構文糖です。完全に言語に依存しない方法で、それ以上のものです。上記の例のように、メソッドのオーバーロードをより便利で関連性の高いものにすることは、実際に既存の言語に追加するのに適した機能である可能性があります(AS3で広く暗黙的に要求されているように)、または、新しい手続き型/オブジェクト指向言語の作成。