6

防御メソッドおよび「仮想拡張メソッド」とも呼ばれるデフォルト メソッドがあります。

私はデフォルト メソッドの多大な価値を高く評価していますが (ある面では C# メソッドよりもさらに強力です)、ソース コードにアクセスせずに既存のインターフェイスを拡張することを許可しないという決定は何だったのだろうかと思います。

SO での彼の回答の 1 つで、 Brian Goetz は、既定のメソッドは利便性とインターフェイスの進化のために非常に設計されていると述べました。したがって、インターフェイスを作成すると、通常は別のクラスに配置する必要があるあらゆる種類のユーティリティ メソッドをそこに詰め込むことができます。それでは、さらに一歩進んで、私たちの管理下にないインターフェースにそれを許可してみませんか?

4

2 に答える 2

9

これは、 API 設計者が API を制御する必要があるという哲学的な信念によって推進されました。外部から API にメソッドを注入することは確かに便利ですが、API 設計者が API を制御するのを弱体化させます。(これは「モンキーパッチ」と呼ばれることもあります。)

用語について: C# で「拡張メソッド」と呼ばれるものは、拡張メソッドの定義ではなく、拡張メソッドの 1 つの形式にすぎません。Java のデフォルト メソッドも拡張メソッドです。主な違いは次のとおりです。C# 拡張メソッドは静的であり、 use-siteで注入されます。Java は仮想および宣言サイトです。次に、C# の拡張メソッドは型に注入されますが、Java の既定のメソッドはクラスのメンバーです。(これにより、他のインスタンス化に影響を与えることなく、C# にsum()メソッドを挿入できます。) List<int>List

C# のアプローチに慣れていれば、これが「正しい」、「通常の」、または「実際の」方法であると考えるのは自然なことですが、実際には、これは多くの可能な方法の 1 つにすぎません。他の投稿者が指摘しているように、C# 拡張メソッドには、Java の既定のメソッドと比較して、非常に重大な欠点がいくつかあります (たとえば、リフレクションの発見可能性が低い、ドキュメントによる発見可能性が低い、オーバーライドできない、アドホックな競合管理規則が必要)。したがって、比較すると、Java グラスは半分以上いっぱいになっています。

于 2015-04-07T14:42:00.627 に答える
8

Brian Goetz は、デフォルト メソッドも便宜上使用されると述べていますが、それがデフォルト メソッドの最初の目標であったことを意味するものではありません。

覚えておいてください: インターフェースの進化をサポートするためにデフォルトのメソッドが存在します。これは、ラムダの導入に直面して非常に必要とされていたものです (ラムダを使用するメソッドの導入は、多くの場合、新しいメソッドを追加する必要があることを意味していたため)。

ただし、C# に存在するため、拡張メソッドに欠点がないかのように投稿を書いています。

  • 拡張メソッドには、発見可能性に大きな問題があります。

    • それらはクラスのドキュメントには表示されません。
    • それらは、クラスを反映することによって公開されることはありません。
    • コードで拡張メソッドが使用されている場合、IDE がなければ、拡張メソッドがどこから来たのかを知る方法はありません。
  • 拡張メソッドは、その性質上、標準的な曖昧さ回避メカニズムの一部を許可しません。

    • 拡張メソッドを使用してクラス メソッドのオーバーロードを定義し、そのオーバーロードまたは同様の拡張メソッドがクラスの作成者によって定義されている場合はどうなりますか? ケース 1: コードは、単純な再コンパイルで新しいメソッドを使用するように切り替わります。ケース 2: コードがコンパイルされなくなりました。
    • そのため、制御できない名前空間に拡張メソッドを配置することを定義することはお勧めしません。このような問題が扱いにくくなる可能性があるためです。ただし、これを行うと、制御していない型の拡張メソッドを発見するのがさらに難しくなります。
  • 拡張メソッドには柔軟性がありません。

    • 拡張メソッドがライブラリによって定義されると、そのライブラリのクライアントがその拡張メソッドの実装を変更または微調整する方法はありません。
    • クライアントが制御しない型の拡張メソッドを定義する場合、ライブラリが同じ拡張メソッドを定義する日に、腕に互換性の問題が発生します。その可能性は、拡張メソッドが何をするか、およびそのライブラリの進化ポリシーに依存します。

これら 3 つの欠点のうち、Java 8 に存在するデフォルトのメソッドにはそれらがありません。

C# に拡張メソッドを含める大きな理由は、LINQ を有効にするためであることに注意してください。Java はそのストリームに別の設計を採用したため、Java 言語の設計者がそれらを当然のこととして追加することはないと思います。

于 2015-04-06T07:13:15.013 に答える