オーバーロードされたメソッドの名前を変更する必要がありますか?


14

これらのメソッドを含むインターフェースを想定します:

Car find(long id);

List<Car> find(String model);

このように名前を変更する方が良いですか?

Car findById(long id);

List findByModel(String model);

実際、このAPIを使用する開発者は、初期find()メソッドの可能な引数を知るためにインターフェイスを調べる必要はありません。

だから私の質問はより一般的です:コードでオーバーロードされたメソッドを使用することの利点は何ですか?


4
一貫している限り、どちらの方法も受け入れられます。
ChrisF

メソッドのオーバーロードとオーバーライドの間には関係があります。しかし、この記事はあなたの提案を好む-それは興味がある可能性がありますroseindia.net/javatutorials/...
NoChance

回答:


23

これは、あなたが影響を受けやすい他の多くの悪い読みやすさの慣行と比較すると、比較的小さな問題です。そのため、メソッドの名前の付け方は主に好みの問題だと思います。

とはいえ、あなたがそれについて何かをするつもりなら、私はこの習慣に従います:

  • 過負荷の場合...

    メソッドはほぼ同じ契約に従いますが、異なる入力で動作します(個人の納税者番号、アカウント番号、または名前と誕生日でアカウントを検索できる電話オペレーターを想像してください)。これには、同じタイプの出力を返すことが含まれます

  • 次の場合は別の名前を使用してください...

    メソッドは実質的に異なることを行うか、異なる出力を返します(あなたの場合のように)。データベースにアクセスし、アクセスしない場合は、別の名前を使用することを検討できます。

    さらに、返される型が異なる場合、動詞も変更して次のことを示します。

    Car findById(long id);
    
    List findAllByModel(String model);
    

3
FWIW、もう少し強く言います。「メソッドはまったく同じ規約に従います...」つまり、引数のタイプ/カウントは関係ありません-関数呼び出しのセマンティクスは関係なく同じです。引数のタイプ/カウントが重要な場合は、オーバーロードしないでください。
mcmcc

4

あらゆる場合に異なる名前を使用することをお勧めします。将来のある時点で、とList<Car> findByMake(String make)は対照的に、別のメソッドを追加したいと思うかもしれませんList<Car> findByModel(String model)。突然、すべてを呼び出すfindと意味がなくなります。また、メソッドの名前が使用方法に関する詳細情報を提供している場合、メソッドが誤って誤って使用される可能性が低くなります。


1
公平を期すと、機能がオブジェクトによって明示的に表されている場合、これは問題ではありません:find(Make val)およびfind(Model val)。次に、などの便利なメソッドfindByMake(String val)が実際に何をしているのかがより明確になります。結局のところ、a Stringはメーカーでもモデルでもないため、メソッドは実際に何をしているのかを説明する必要があります。
ニコール

4

メソッドの名前を変更すると、オーバーロードされなくなります。それ自体で、オーバーロードは必ずしもコードの可読性を低下させるわけではありませんが、構文が明確でない場合、実装を追跡するのが難しくなります。

多くの言語は、パラメーターがオプションであり、オプションのパラメーターのデフォルトが暗示される機能へのインターフェースを提示する手段として、メソッドのオーバーロードを使用します。これは、メソッド宣言でデフォルトのパラメーター構文をサポートしていない言語に特に当てはまります。

これを行う:

void MyMethod(int param1, int param2 = 10)
{
    ...
}

これを行うことからあなたを救います:

void MyMethod(int param1)
{
    MyMethod(param1, Param2Default);
}

void MyMethod(int param1, int param2)
{
    ....
}

どちらがより読みやすいかは、あなた次第です。個人的には、特にパラメーターリストが少し長くなっている場合、2番目のオプションを好みますが、API全体で一貫している限り、それは実際には重要ではないと思います。

オーバーロードの難しさは、基本的に同じことを行う関数が必要な場合、およびパラメーターリストを同じにし、戻り値の型を異なるようにする場合に発生します。ほとんどの言語は、同じ名前の異なる戻り値型を持つ2つのメソッドを区別する方法を知りません。この時点で、ジェネリックを使用するか、パラメータインターフェイスを変更するか、メソッドの名前を変更して戻り値の型の違いを示すことを検討する必要があります。このような状況に対処するためのシンプルで明確な命名スキームに決着しないと、読みやすさが大きな問題になる可能性があります。

オーバーロードされたメソッドに名前を付けるGetSomething()GetSomethingEx()、メソッド間の違いが何であるかについては特に言及しません。特に、戻り値のタイプだけが違います。一方、GetSomethingAsInt()及びGetSomethingAsString()方法は、厳密に過負荷をして、しばらくしていないものについて、もう少しあなたを教えて、2つの方法が同様のことを行うことを示している、まだ別の値の型を返すん。メソッドに名前を付けることのできる他の方法があることは知っていますが、ポイントを説明するために、これらの大雑把な例はすべきです。

OPの例では、メソッドのパラメーターが異なるため、名前の変更は厳密には必要ありませんが、メソッドをより具体的に名前を付けると少しわかりやすくなります。最終的には、ユーザーに提示したいインターフェースのタイプに本当に帰着します。読みやすさに関するあなた自身の認識だけに基づいて、過負荷にしないかどうかの決定を下すべきではありません。メソッドをオーバーロードすると、たとえばAPIインターフェースが単純化され、開発者が覚えておく必要のあるメソッドの数を減らすことができます。一方、インターフェースを難読化すると、開発者がメソッドのドキュメントを読んでどのフォームを理解する必要があるかがわかります使用するメソッドの種類。ただし、多くの同様でありながら説明的な名前のメソッドがあると、目的に関してメソッド名を読むだけでより明確になります。


0

メソッドが同じものを返し、同じ規約に従う限り、オーバーロードを優先します。オーバーロードにより、呼び出し側のコードがパラメータータイプに不必要にコミットすることがなくなります。

呼び出し元の関数がパラメーターとして検索クエリを受け取り、への呼び出しの前後に他の処理を実行するとしfindます。

void tryToSellCars(String which) {
    /* grab an airhorn, inflatable tube guy... */
    List<Car> cars = find(which);
    /* expound virtues of each car in detail... */
}

何らかの理由でそのクエリのタイプを変更したい場合(たとえば、単純なID文字列から何らかの機能を備えた完全なクエリオブジェクトに)、関数のシグネチャを変更するだけで、呼び出し元の関数でその変更を行うことができます。クラスで呼び出すメソッドの変更を気にせずに新しいパラメータタイプを受け入れます。

void tryToSellCar(CarQuery which) {
    /* grab airhorn, inflate tube guy... */
    List<Car> cars = find(which)
    /* expound virtues of each car in detail... */
}

あなたが実装する場合findByIdfindByQueryObject、別途、あなたはその変更をするためにすべての呼び出しを追い詰めるしなければなりません。例では、1つの単語を変更するだけで完了しました。


もちろん、この答えは、無効なパラメーターのコンパイル時エラーによるオーバーロードをサポートする言語を使用していることを前提としています。JavaScript、Ruby、またはオーバーロードをネイティブにサポートしない他の言語を作成している場合findByFoo、型の不一致を早期に検出するために常に冗長を使用します。
sqykly
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.