Javaを探しています。現在、Java 8のデフォルトメソッドについて読んでいますが、 、これらはインターフェイスにのみ追加できます...
...インターフェイスを実装しない最終クラスの拡張メソッドを記述できる言語機能はありますか? (ラップする必要はありません...)
C#拡張メソッドは、拡張型を最初の引数として使用する静的メソッドの単なる構文上の砂糖です。 Javaデフォルトのメソッドはまったく異なるものです。C#拡張メソッドを模倣するには、通常の静的メソッドを記述するだけです。ただし、シンタックスシュガーはありません; Javaはこの機能はありません。
Javaのデフォルトメソッドは、実際の仮想メソッドです。たとえば、オーバーライドできます。デフォルトのfoo()
メソッドを宣言するインターフェースX
から継承するクラスI
を考えてください。 X
またはそのスーパークラスのいずれかが独自のfoo()
メソッドを宣言しない場合、X
はI
のfoo()
実装を取得します。現在、Y
のサブクラスX
は、通常のメソッドのようにX.foo()
をオーバーライドできます。したがって、デフォルトのメソッドは構文上の砂糖だけではありません。これらはメソッドのオーバーライドと継承メカニズムの実際の拡張であり、他の言語機能では模倣できません。
デフォルトメソッドは特別なVMサポートを必要とするため、コンパイラのみの機能ではありません。クラスのロード中、クラスの階層をチェックして、継承するデフォルトメソッドを決定する必要があります。 、この決定はコンパイル時ではなく実行時に行われます。それについてのクールなことは、継承するインターフェイスが新しいデフォルトメソッドを取得するときにクラスを再コンパイルする必要がないことです:VMクラスのロード時に、新しいメソッドをそれに割り当てます。
Javaには拡張メソッドがありません。デフォルトのメソッドは拡張メソッドではありません。各機能を見てみましょう。
解決された問題:
Javaのデフォルトメソッドは、デフォルトの実装をインターフェイスに追加する機能です。そのため、インターフェイスを拡張するオブジェクトはメソッドを実装する必要がなく、デフォルトのメソッドを使用するだけで済みます。
interface IA { default public int AddOne(int i) { return i + 1; } }
IAを実装するオブジェクトは、使用される既定のメソッドがあるため、AddOneを実装する必要はありません。
public class MyClass implements IA { /* No AddOne implementation needed */ }
C#にはこの機能がなく、この機能を追加することで大幅に改善されます。 (更新:C#8の機能)
解決された問題:
例:型文字列はC#のシールドクラスです。文字列はシールされているため、継承できません。ただし、文字列から呼び出すことができるメソッドを追加できます。
var a = "mystring";
a.MyExtensionMethed()
Javaにはこの機能がなく、この機能を追加することで大幅に改善されます。
JavaのデフォルトメソッドとC#の拡張メソッド機能については、類似したものはありません。それらは完全に異なり、完全に異なる問題を解決します。
C#拡張メソッドはstaticおよびse-siteですが、Javaのデフォルトメソッドはvirtualおよびdeclaration-siteです。
私があなたが望んでいると思うことは、あなたが制御していないクラスにメソッドを「モンキーパッチ」する機能ですが、Javaはあなたにそれを与えません(設計により;拒否されました。)
C#アプローチに対するデフォルトメソッドのもう1つの利点は、それらが反射的に発見可能であり、実際、外部からは「通常の」インターフェイスメソッドと何も変わらないように見えることです。
Javaのデフォルトメソッドに対するC#の拡張メソッドの利点の1つは、C#の具象ジェネリックを使用すると、拡張メソッドがclassesではなくtypesに注入されるため、sum()
メソッドを_List<int>
_に挿入します。
とりわけ、JavaのデフォルトメソッドとC#の拡張メソッドの主な哲学的な違いは、C#ではメソッドを型にインジェクトできることです制御しません(開発者にとっては確実に便利です)一方で、Javaの拡張メソッドはそれらが現れるAPIの第一級の部分(それらはインターフェースで宣言されている、反射的に発見可能など)これはいくつかの設計原則を反映しています。ライブラリ開発者はAPIの制御を維持でき、ライブラリの使用は透過的である必要があります。タイプY
でメソッドx()
を呼び出すことは、どこでも同じことを意味する必要があります。
拡張メソッドにいくつかのトリックを含めることは可能です。
LombokまたはXTendを試すことができます。拡張メソッドには、すぐに使用できるJava実装はありませんが、LombokとXTendの両方が完全に機能するソリューションを提供します。
Lombokはシンプルなスタンドアロンコード処理フレームワークであり、拡張メソッドを含む、批判されているJava固有の面倒な作業のほとんどを軽減します。 https://projectlombok.org/features/experimental/ExtensionMethod.html
Xtend http://www.Eclipse.org/xtend/ は数光年先に進み、Scalaなどの現代言語の最良の部分を組み合わせた言語を実装しますJavaおよびJava型システムの上。これにより、一部のクラスをXtendに実装し、他のクラスを同じプロジェクト内のJavaに実装できます。 Xtendコードは有効なJavaコードに準拠しているため、JVMマジックは内部で発生しません。一方、不足している拡張メソッドのみがある場合は少し多すぎます。
JPropel https://github.com/nicholas22/jpropel-light は、Lombokを使用してJavaでLINQスタイルの拡張メソッドを実装します。それは一見の価値があるかもしれません:)