web-dev-qa-db-ja.com

Java C#拡張メソッドと同等

拡張メソッドを使用してC#で行うように、オブジェクトのリストに機能を実装することを検討しています。

このようなもの:

List<DataObject> list;
// ... List initialization.
list.getData(id);

Javaでそれを行うにはどうすればよいですか?

161
Fabio Milheiro

Javaは拡張メソッドをサポートしていません。

代わりに、通常の静的メソッドを作成するか、独自のクラスを作成できます。

177
SLaks

拡張メソッドは単なる静的メソッドではなく、単なる便利な構文シュガーではありません。実際、非常に強力なツールです。主なものは、異なるジェネリックのパラメーターのインスタンス化に基づいて異なるメソッドをオーバーライドする機能です。これはHaskellの型クラスに似ており、実際、C#のMonad(つまりLINQ)をサポートするためにC#にあるように見えます。 LINQ構文を削除しても、Javaで同様のインターフェイスを実装する方法はまだわかりません。

また、Javaのジェネリックパラメーターの型消去のセマンティクスのため、Javaでそれらを実装することは不可能だと思います。

51
user1686250

Project Lombok は、注釈を提供します @ExtensionMethod は、必要な機能を実現するために使用できます。

16
Thomas Eizinger

XTend language —これはJavaのスーパーセットであり、Javaソースコードにコンパイルされます1—これをサポートします。

7
Sam Keays

もう1つのオプションは、 ForwardingXXX google-guavaライブラリのクラスを使用することです。

6

Javaにはそのような機能はありません。代わりに、リスト実装の通常のサブクラスを作成するか、匿名の内部クラスを作成できます。

List<String> list = new ArrayList<String>() {
   public String getData() {
       return ""; // add your implementation here. 
   }
};

問題は、このメソッドを呼び出すことです。 「所定の場所で」実行できます。

new ArrayList<String>() {
   public String getData() {
       return ""; // add your implementation here. 
   }
}.getData();
6
AlexR

技術的には、C#拡張にはJavaに相当するものはありません。しかし、よりクリーンなコードと保守性のためにそのような関数を実装したい場合は、Manifoldフレームワークを使用する必要があります。

package extensions.Java.lang.String;

import manifold.ext.api.*;

@Extension
public class MyStringExtension {

  public static void print(@This String thiz) {
    System.out.println(thiz);
  }

  @Extension
  public static String lineSeparator() {
    return System.lineSeparator();
  }
}
6
M.Laida

マニホールド は、C#スタイルのJavaを提供します 拡張メソッド およびその他のいくつかの機能。他のツールとは異なり、マニフォールドには制限がなく、ジェネリック、ラムダ、IDEなどの問題から suffer がありません。マニフォールドは、F#スタイル カスタムtypes 、TypeScriptスタイル 構造インターフェース 、およびJavaScriptスタイル expandoタイプ

さらに、IntelliJはManifold plugin を介してManifoldの包括的なサポートを提供します。

Manifoldは、 github で利用可能なオープンソースプロジェクトです。

5
Scott

Defenderメソッド(つまり、デフォルトのメソッド)がJava 8になる可能性はわずかにありますが、私が理解している限り、author任意のユーザーではなく、interfaceを遡及的に拡張します。

Defenderメソッド+インターフェイスインジェクションはC#スタイルの拡張メソッドを完全に実装できますが、AFAICS、インターフェイスインジェクションはまだJava 8ロードマップにはありません。

4
Jörg W Mittag

この質問でパーティーに少し遅れましたが、誰かがそれを便利だと思う場合に備えて、サブクラスを作成しました。

public class ArrayList2<T> extends ArrayList<T> 
{
    private static final long serialVersionUID = 1L;

    public T getLast()
    {
        if (this.isEmpty())
        {
            return null;
        }
        else
        {       
            return this.get(this.size() - 1);
        }
    }
}
3
magritte

装飾オブジェクト指向設計パターン を使用できます。 Javaの標準ライブラリで使用されているこのパターンの例は、 DataOutputStream です。

リストの機能を強化するためのコードを次に示します。

public class ListDecorator<E> implements List<E>
{
    public final List<E> wrapee;

    public ListDecorator(List<E> wrapee)
    {
        this.wrapee = wrapee;
    }

    // implementation of all the list's methods here...

    public <R> ListDecorator<R> map(Transform<E,R> transformer)
    {
        ArrayList<R> result = new ArrayList<R>(size());
        for (E element : this)
        {
            R transformed = transformer.transform(element);
            result.add(transformed);
        }
        return new ListDecorator<R>(result);
    }
}

PS私は Kotlin の大ファンです。拡張メソッドがあり、JVMでも実行されます。

1
Eric