Javaでインターフェースを実装する場合のデフォルトとImpl


34

読んだ後、パッケージ名は単数形か複数形か?私は、自分のペットの探求の1つであるインターフェイスの実装の命名に関する適切な議論を見たことがないことに気付きました。

Orderさまざまな方法で実装することを目的としたインターフェースを持っているが、プロジェクトが最初に作成されたときの最初の実装のみがあると仮定しましょう。あなたはのために行くかDefaultOrderまたはOrderImpl虚偽の二分法を避けるために、または他のいくつかの変種?そして、実装が増えたらどうしますか?

そして最も重要なのはなぜですか?

回答:


59

名前には意味を伝える機会があります。なぜあなたはImplでその機会を捨てるのですか?

まず、実装が1つしかない場合は、インターフェースを廃止します。 この命名の問題を作成し、何も追加しません。さらに悪いことに、あなたと他のすべての開発者が常にインターフェイスのみを使用することに注意を払わないと、APIの一貫性のないメソッドシグネチャで問題が発生する可能性があります。

それを考えると、すべてのインターフェイス 2つ以上の実装を持っているか、持っていると仮定できます。

  • 現在1つしかなく、もう1 つがどのように異なるかわからない場合は、デフォルトが良いスタートです。

  • 現在2つある場合は、目的に応じてそれぞれ名前を付けます。

    例:最近、具体的なクラスContextがありました(データベースを参照)。オフラインのコンテキストを表現できるようにする必要があるため、Contextという名前を新しいインターフェイスに使用し(古いAPIとの互換性を維持するため)、新しい実装OfflineContextを作成しました。しかし、元の名前が何に変更されたと思いますか?そうです、ContextImpl(いいね)。

    この場合、DefaultContextはおそらく大丈夫であり、人々はそれを取得しますが、それは可能な限り記述的ではありません。結局のところ、それがオフラインない場合、それは何ですか?そこで、OnlineContextを使用しました


特殊なケース: インターフェイスで「I」プレフィックスを使用する

他の回答の 1つは、インターフェイスでIプレフィックスを使用することを提案しました。できれば、これを行う必要ありません。

ただし、カスタム実装のために両方のインターフェースが必要であるが、頻繁に使用される主要な具体的な実装もあり、その基本名が単純すぎるためにインターフェースだけを放棄できない場合は、追加を検討できますインターフェイスへの「私」(ただし、それがまだあなたとあなたのチームにとって適切でない場合は完全に問題ありません)。

例:多くのオブジェクトは「EventDispatcher」になることができます。APIのために、これはインターフェイスに準拠する必要があります。ただし、委任用の基本的なイベントディスパッチャーも提供する必要があります。 DefaultEventDispatcherは問題ありませんが、少し長くなります。名前を頻繁に表示する場合、具体的なクラスにはベース名EventDispatcherを使用し、カスタム実装にはIEventDispatcherを実装することをお勧めします。

/* Option 1, traditional verbose naming: */
interface EventDispatcher { /* interface for all event dispatchers */ }
class DefaultEventDispatcher implements EventDispatcher {
  /* default event dispatcher */
}

/* Option 2, "I" abbreviation because "EventDispatcher" will be a common default: */
interface IEventDispatcher { /* interface for all event dispatchers */ }
class EventDispatcher implements IEventDispatcher {
  /* default event dispatcher. */
}

3
+1は確実な答えです。Implを使用しない理由のように。
ゲイリーロウ

2
+1は完全に同意します。インターフェイスが表すドメインの概念から離れた名前を付けることは、その点を完全に欠いています。
rupjones

9
「実装が1つしかない場合」、実装が1つしかないことを事前にどのように知っていますか?「すべてのインターフェースが2つ以上の実装を持っているか、持っているかもしれません」... 2番目のものを実装する前に。
Tulainsコルドバ

2
@NickC私はセマンティクスについて教訓的ではありません(私は詩人であり、私もそれを知りませんでした)。英語は私の母国語ではないので、私はそれについて熱心ではありません。私は欠陥のあるロジックについて話していました。分離にはインターフェースを使用します。それには、特定の実装数は必要ありません。
Tulainsコルドバ

4
if you will only ever have one implementation, do away with the interface-コンポーネントをテストする場合を除きます。その場合、MockOrder、OrderStubなどを作成するためにそのインターフェイスを保持する必要があります。
JBRウィルキンソン14

15

インターフェースのユースケースによって命名を決定します。

インターフェースをデカップリングに使用する場合、Impl実装に選択します。

インターフェースの目的が行動の抽象化である場合、実装は具体的に実行していることに応じて名前が付けられます。私はよくそれにインターフェース名を追加します。したがって、インターフェイスが呼び出される場合はValidator、を使用しますFooValidator

それDefaultは非常に悪い選択だと思います。最初にコード補完機能を汚染します。名前は常にそれで始まるためです。もう1つは、デフォルトは時間の経過とともに変更される可能性があることです。そのため、最初にデフォルトになる可能性のあるものは、非推奨の機能になった後しばらくしてからです。そのため、デフォルトが変更されるとすぐにクラスの名前を変更し始めるか、誤解を招く名前で生活します。


8

Nicoleの答えには同意します(特にほとんどの場合、インターフェイスはおそらく必要ないでしょう)が、議論のために、OrderImpland 以外の追加の代替手段を捨てますDefaultOrder:のような静的ファクトリメソッドの背後に実装を隠しOrders.create()ます。例えば:

public final class Orders {
  public static Order create() {
    return new Order() {
      // Implementation goes here.
    };
  }
}

このアプローチを使用すると、実装は匿名の内部クラスになったり、名前を持つDefaultまたはImpl名前に含まれるプライベートクラスになったり、完全に別の名前になったりする可能性があります。どちらを選択しても、発信者は気にする必要はありません。そのため、いつでも、いつ変更するかを決める際に、柔軟性が高まります。

実際のこのパターンの優れた例のいくつかはjava.util.Collectionsjava.util.concurrent.Executorsユーティリティクラスであり、そのメソッドは非表示の実装を返します。効果的なJavaが(項目1で)言及しているように、このパターンはAPIの「概念的な重み」を小さく保つのに役立ちます。


興味深い追加の場合は+1:匿名の実装。
ゲイリーロウ

1
グアバでも広く使用されています。
ニコール

3

インターフェースのOrderImpl直後にアルファベット順に表示されるので、私はいつも行きOrderます。


2
そして、特別な処理など、進行中のさらなる実装をどのように処理しますか?
ゲイリーロウ

1
最初の実装について尋ねました。DomesticOrder、ForeignOrder、またはその他の実装を開始すると、アルファベットでの位置に関係なく、より慎重に名前が付けられます。
ベンホフスタイン

まったく正しい-元の質問を編集して、この新しい要件を反映させました。
ゲイリーロウ

複数の実装が予定されている場合はお勧めできません。
サデフ

0

インターフェースにプレフィックスI(IWhatever)を付けて、実装をwhateverにすることができます。

公式のJavaコード規約では、この種のインターフェースの命名については言及していませんが、この種の命名は認識とナビゲーションに役立ちます。


インターフェイスの前にIを付けるのはなぜですか?ナビゲーションでの認識を支援するためですか?
ゲイリーロウ

@Gary:インターフェイスタイプにIをプレフィックスすることは、Delphi言語で確立された慣習です。Delphiクラスでは、型の先頭にTが付きます。したがって、特定の実装としてTSomethingOrderとTBul FotosearchOrderを備えたIOrderインターフェイスとTOrderデフォルト実装があります。
マルジャンヴェネマ

3
.NET開発でもこの規則が頻繁に使用されるのを見てきました。おそらく、Microsoftのドキュメントと例で使用されているためです。
ベンホフシュタイン

5
@Renesisは、Javaで@Renesisを使用する便利なケースを見つけたようです。個人的には、IDEを使用して違いを教えてくれました。
ゲイリーロウ

0

場合によってはDefaultが意味をなすこともありますが、実装を説明する方が役立つと思います。あなたのインターフェースがあるのであればUserProfileDAO、あなたの実装が可能UserProfileSQLDAOか、UserProfileLDAPDAOまたはそのような何か。


0

可能であれば、その処理の内容/方法に基づいて名前を付けます。

通常、最悪のアプローチは、使用方法に基づいて命名することです。

実装の基本クラスとして使用されることになっている場合、BaseXまたはAbstractXを使用できます(抽象の場合(ただし、何をしなかった場合は作成しないので、それを実行して絞り込みますインターフェース)。可能な限り最も単純な機能を提供し、そのような機能で十分な場合に(拡張ではなく)直接使用することが期待される場合、SimpleXまたはBasicXと呼ぶことができます。

他の実装が提供されない限り使用される場合は、DefaultXという名前を付けます


-2

これらの回答のほとんどは、何が行われているかを説明していますが、理由は説明していません。

オブジェクト指向の原則はどうなりましたか?Implはクラスとその使用方法について教えてくれますか?どのように構成されているかではなく、使用法を理解することに関心を持つ必要があります。

Personインターフェイスを作成する場合、PersonImplとは何ですか?無意味。少なくともDefaultPersonは、コードを作成した人がインターフェイスを作成してはならないことを教えてくれます。

インターフェイスはポリモーフィズムのために入力されているため、そのまま使用する必要があります。


1
@NickCから受け入れられた回答は、何が行われているのか、そしてその理由についてある程度詳しく述べています。
ゲイリーロウ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.