1

私はしばしば、Java クラスを適切に装飾できるようにしたいと考えていました。つまり、Java クラスに動作を追加することです。私は ruby​​ の mixin を知っていますが、それらがひどく混乱する可能性があることも知っています。

私は、次のような言語構造を持つという理論的なアイデアを思いつきました。

package org.test.decorator;

public decorator ListPatch<E> extends List<E> {
    public E last() {
        return this.get(this.size() - 1);
    }
}

thisListの公開メンバーとデコレーター自体へのアクセスを提供します。

次に、クラスで使用できます:

package org.test.decorator;

decoration org.test.decorator.ListPatch;

public MyClass {
    public void foo() {
        List<String> list = Lists.newArrayList();
        list.add("test");
        System.out.println(list.last());
    }
}

私はコンパイラについてあまり知識がないので、そのようなことが可能かどうか疑問に思いました。また、それが実際に改善されるかどうか。

4

3 に答える 3

2

確かに、それは可能です。

Scalaがバイトコードにコンパイルされ(そしてScalaクラスからバイトコードクラスへのかなり簡単なマッピングがあり)、ミックスインをサポートしているという事実は、これを証明しています。

サンプルコードがScala構文でどのように表示されるかを次に示します。

class ListTest {

    // ...

}

trait ListPatch {
    def last {
        // ...
    }
}

object Main {
    def main(args: Array[String]) {
        val list = new ListTest() with ListPatch;
        list.add("test")
        println(list.last)
    }
}

Scalaは、とMain$$anon$1を構成する腋窩クラスを追加することでこれをコンパイルします。ListTestListPatch

Java開発者のモットーは、常に「疑わしい場合は除外する」でした(そしておそらく常にそうなるでしょう) 。けれど。

関連する質問:

于 2012-07-29T21:55:27.173 に答える
1

実際にはあなたの質問に対する答えではありませんが、制御/依存性注入を反転させることでこの問題を解決できます(コードで行ったように)

基本的に:「newArrayList()」を使用せず、代わりに「injector.new(ArrayList.class)」のようなファクトリを使用します。このインジェクターは、必要なクラスをオーバーライドして、メソッドで装飾されたArrayListを拡張するオブジェクトを返すことができるようになりました。

于 2012-07-29T21:57:40.693 に答える
1

Your idea sounds much like Extension methods in C#.

Extension methods enable you to "add" methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type.

In C# you would write your example as:

public static class ListExtensions
{
    public E Last(this List<E> list)
    {
        return list[list.Count - 1];
    }
}

Using it like this:

List<String> list = new List<String>();
list.Add("test");
Console.WriteLine(list.Last());

So, from a design perspective it can certainly be designed and added. However, there are other considerations that come into play when adding something to an existing language, such as syntax conflicts, backwards compatibility, edge cases, and cost of designing and coding it versus the benefits it provides.

Eric Lippert has a great blog about Extension Properties (a natural extension of Extension Methods) in C#, and in the second part he highlights some of the aspects that affect why doesn't product X have feature Y?, which I'm sure also applies to Java and its development.

于 2012-07-29T21:59:11.443 に答える