関数のオーバーロードの使用/利点は何ですか?
IMO、主な利点は、非常に類似したタスクを論理的に実行し、異なるパラメーターを受け入れることでわずかに異なるメソッド/関数の命名の一貫性です。これにより、同じメソッド名を複数の実装で再利用できます。
例えばオーバーロード:(良い)
function Person[] FindPersons(string nameOfPerson) { ... }
function Person[] FindPersons(date dateOfBirth) { ... }
function Person[] FindPersons(int age, string dogsName) { ... }
「一意に名前が付けられた」関数よりも望ましい:(悪い)
function Person[] FindPersonsByName(string nameOfPerson) { ... }
function Person[] FindPersonsByDOB(date dateOfBirth) { ... }
function Person[] FindPersonsByAgeAndDogsName(int age, string dogsName) { ... }
このように、これらの関数を呼び出す/使用するクライアントを作成するコーダーは、より高いレベルの概念的思考(「私は人を見つける必要がある」)で動作でき、考案された関数名を覚えたり探したりする必要がありません。
静的型付けを使用すると、コンパイラーは、使用パラメーターに基づいて、該当するオーバーロードに一致するようになります。動的型付けの場合、これと同じ一致が実行時に発生し、適切な一致が見つからない場合は失敗する可能性があります。
非常に有効な質問です。
命名の一貫性は得られますが、正確な実装についての曖昧さが犠牲になります。
本当の問題は、メソッド名の人間の記憶ですよね?一般的に使用されている名前を覚えておくと簡単です。
タイピングの経済性、メソッド名の短縮を可能にしますか?異なる名前の数が少ないほど、(数学的に)名前自体の情報量が少なくなります。
最初の数文字とパラメーター/戻り値のタイプに基づいてメソッド名をすばやく検索/推測/挿入するIDEでは、これらの2つの問題は問題になりません。
しかし、コーディングの正確さにはコストと利点があると思います。
オーバーロードは、ポリモーフィズムの一種です。プログラマーは、名前を変更せずに、さまざまなタイプのデータに対して概念的に同じことを行う関数を作成できます。 (また、プログラマーがパラメーターに応じて概念的に異なることを行う関数を作成することもできますが、それは本当に悪い考えです。)
これにより、表記の一貫性が保たれ、コードの読み取りと書き込みの両方に適しています。 I/Oは非常に一般的な用途です。一般的に使用されているほとんどの言語では、printf()
やkin in C、operator<<()
in C++、PRINT
inなど、好きなものを出力する関数または演算子があります。何でも使っていた古いベーシック。 printint()
、printstring()
、printfloat()
などの関数を必要とする言語は、これまでキャッチされていません。
これは、コードの作成時に変数の型が何であるかが必ずしもわからないC++テンプレートやその他の構成要素と非常にうまく機能します。
関数は、いくつかのオプションの詳細を処理する必要がある場合があります。たとえば、次の例では、ユーザーが知っている詳細を含めて、Membersオブジェクトにメンバーを追加します。ここで、ageはメンバーを作成するための最小の詳細であり、ageとmemberOfはオプションです。 [注:関数の定義はコードスニペットでは提供されていません。]
public class Members
{
public System.Collections.Generic.List<Member> TeamMembers;
public AddMember(Member m) {}
public AddMember(string name) {}
public AddMember(string name, int age) {}
public AddMember(string name, int age, string[] memberOf) {}
public class Member
{
public string Name { get; set; }
public int Age { get; set; }
public string[] MemberOf { get; set; }
}
}
メソッドを複数のタイプのオブジェクトに適したものにしたい場合があります。例: Console.WriteLine()メソッドは、空の行、bool、int、string、char []、floatなどをコンソールに書き込むことができます。これは、関数のオーバーロードにより可能になりました。
関数/メソッドは、それを実行するために、さまざまな種類のパラメーターを受け取ることができる場合があります。これは関数のオーバーロードの時間です。それ以外の場合は、同じ機能に対して異なる関数を使用する必要がありますが、これは混乱を招き、悪い習慣です。
オブジェクトの属性に関して、同じオブジェクトに複数の動作を提供します。
たとえば、addUs(a,b)
というメソッドは、a
とb
を追加します。
したがって、定義は次のようになります。
_int addUs(int a, int b){
return a+b;
}
_
しかし、引数をクラスのオブジェクトにしたい場合は、次のようにします。
_class Demo{
int height;
int width;
}
_
同じ関数addUs()
が、渡された2つの引数の高さと幅の合計として値を持つ属性の高さと幅を持つ新しいオブジェクトを返すようにします。
したがって、定義は次のようになります。
_Demo addUs(Demo a Demo b){
Demo this;
this.height = a.height + b.height;
this.width = a.width + b.width;
return this;
}
_
コンテキストと利用可能な入力に基づいて同じことを達成する複数の方法がある場合があります。タイプが厳密な静的言語の場合、関数定義はかなり厳格であり、事前に明示的に定義する必要があります。
コンストラクターは、通常、この最も典型的な例です。複雑なオブジェクトを構築していて、すべての要素がない場合でも、必要なものをコンストラクターに渡して残りを埋めることができるようにしたいでしょう。そして、あなたが持っているものは非常に異なり、コンストラクタへのパラメータとしてさまざまな方法で定義する必要があります。
ad-hoc polymorphism は良いものです!!
これは同じ名前の機能のメカニズムですが、インスタンスごとに異なるタスクを実行します。一般的に使用されている名前は簡単に覚えています。
異なるパラメーターを使用して、コード内で同様のことを行いたい場合があります。すべての関数に異なる名前を付ける必要がある場合、コードの読みやすさが非常に悪くなります。