0

私が遊んでいる興味深いアーキテクチャがあります。ユーザーは StoredObject を含む Store を作成できます。ストアは、インターフェイス (つまり、Get、Put、Print) によって表されるさまざまな操作をサポートできます。

これは非常に単純化されたもので、次のようになります。

interface Put<Foo>{
   public void put(Foo f); 
}

class Store implements Put<Store.Obj<?>> {
    class Obj<T> {
        public T o;
    }
    @Override
    public void put(Obj<?> o) { }


}

public class Main {
        public static void main(String[] args){
                Store s = new Store();
                Store.Obj<String> o = s.new Obj<>();
                s.put(o);

        }
}

同様の「get」メソッドを実装したいときに問題が発生します。理想的には、次のようなインターフェイスが必要です。

interface Get<Foo> {
    public <T> T get(Foo<T> f);
}

明らかに、これは不正な Java です。これが意図していることを達成するために使用できる構文 (またはハック) はありますか? 事実上、定数型をジェネリック パラメーターとして指定する代わりに、パラメーター化可能な型をジェネリック パラメーターとして指定したいと考えています (それ自体が get メソッドでパラメーター化されます)。はい、これは Java にはない高次の型に要約されます。クレイジーで醜いハックは大歓迎です!

他の設計上の制約により機能しない一般的なソリューション:

  • get/put/etc 操作を内部Objクラスに移動する
  • Store.Obj<T>ジェネリックパラメーターではなく、スーパータイプを作成し、それを取るインターフェイスを指定します。
4

2 に答える 2

0

Obj から T を取得する方法が必要です。これをGetterと呼びましょう。

interface Getter<O, I> {
    I get(O outer); // get the "inner" value out of the "outer" object
}

Objこれで、クラスにゲッターを実装できます。

class ObjTGetter<T> implements Getter<Obj<T>, T> {
    public T get(Obj<T> o) { return o.o; }
}

StoreコンストラクターにもGetterパラメーターが含まれている必要があるため、それを使用して get を実装できます。Store クラスは次のようになります。

class Store<O, I> implements Put<O>, Get<O, I> {
    private Getter<O, I> getter;
    public void put(O o) { … }
    public I get(O o) { … }
}

Storeしかし、それまでに、ゲッターを直接削除して使用することもできます。

于 2015-01-30T10:19:37.773 に答える
0

最初から高次の型を忘れることができると思います。あなたが提案したことは不可能であることを知っています。

これはおそらくあなたが望んでいる解決策ではありませんが、これは問題に対する私の最高の短所でした.

新しいパラメトリック タイプを作成できないため、代わりに新しいパラメトリック値を作成する必要があります。

まず、それがFooジェネリック型であることを述べる必要があります。実際のところ、Java 8 にはより優れた型があります。Supplier<T>

interface Supplier<T> {
  T get()
}

さて、このタイプの値が必要だったとしましょう:

Supplier<String> s = () -> "Hello";
Supplier<Integer> i = () -> 42;

すでに確立されているように、上位の種類の型がないためGet、コンパイル時にインターフェイスをいくつかのジェネリック型と結合する必要があります。

interface Get<S, F extends Supplier<S>> {
    public S get(Supplier<S> foo);
}

Get問題は、明らかに、すべての可能な型 T に対しての複数のインスタンス/値が必要になることです。Supplier<T>そのため、値が爆発的に増加します。

Get<String, Supplier<String>> f = Supplier::get;
Get<Integer, Supplier<Integer>> g = Supplier::get;

そして、私たちはできる

String m = f.get(); //yield "Hello"
Integer n = g.get(); //yields 42

サプライヤには、必要なものをほとんど含めることができますが、複数の Get インスタンスを定義することから逃れることはできないと思います。

于 2015-01-30T13:03:53.050 に答える