8

現在取り組んでいるオープン ソース プロジェクトの API を作成しようとしていますが、現在の API とセマンティクスの一貫性を保ちながら API を拡張しようとするとスピード バンプにぶつかりました。私が望むのは、任意のメソッド シグネチャを呼び出した結果を受け入れるジェネリック パラメーターを使用してメソッド シグネチャを定義できるようにすることです。「任意」とは、メソッドを含むことを意味しますvoid。のパラメーターの型を直接定義できないことは既に知っていますvoid。明らかな事実を繰り返さないでください。voidメソッド呼び出しをメソッドへの引数として提供できる (つまり、無視する)トリックがあるかどうかは明らかではありません。

バックストーリーなので、なぜ私がそのようなことをしたいのか、そして上記が不可能な場合に備えて、私の設計目標と制約は何かをもう少し理解できます(私が恐れているように):

私の現在の API は、次のような非常に反復可能なメソッドのパターンを定義しています。

public <T,V> Function<T,V> functionFor(V ignoredRetVal) {...}
public <T>   Predicate<T>  predicateFor(V ignoredRetVal) {...}
public <T>   Filter<T>     filterFor(V ignoredRetVal) {...}

名前が示すように、パラメーターは無視され、実装でも使用されません。使用法でignoredRetValは、動的プロキシへのメソッド呼び出しに置き換えられます。パラメータはメソッドが呼び出される前に評価されるため、この動的プロキシ メソッドは外側の関数 (functionForまたはpredicateForなど) の前に呼び出されます。動的プロキシ呼び出しは、呼び出されたMethod(またはメソッド チェーン) を記録し、これをFunction複数の機能ライブラリからオブジェクト (Guava) または他の関数のようなオブジェクトに変換します。

私が今やろうとしているのは、戻り値の型 ( Functional Java の Effectなど) を必要とせずに、副作用のみに使用されるメソッド呼び出しをキャプチャする同様のセマンティックを作成することです。無効でない戻り値の型が提供されている場合、それは無視されます。 . void の戻り値の型が提供された場合, それも無視されて受け入れられます. 重要なのは, セマンティクスが何らかの形でプロキシメソッドを強制的に呼び出さなければならないということです.効果、候補メソッドにはメソッドが含まれる可能性が高く、void理想的には次のようになります。

public <T, V> Effect<T> effectFor(V ignoredRetVal) {...}

(これは既に void 以外の戻り値の型で機能します)、次のように使用できます。

Effect<MyClass> effect1 = effectFor (proxyOfMyClass.nonVoidMethod());// OK :-)
Effect<MyClass> effect2 = effectFor (proxyOfMyClass.orVoidMethod()); // Problem!!

私が言ったように、私が探しているセマンティックは直接サポートできません。そうでない場合、代替案は、私が確立したパターンに精神的に近いはずです。また、私の API の全体的な目標は、内部クラスの実装の「垂直方向のノイズ」を減らすことでした。私は Double Brace Initializers のファンではありません。提案が何であれ、簡潔さをサポートするセマンティック、特に単一ステートメントのセマンティックを探しています。

4

1 に答える 1

1

void特にダブルブレースハックが気に入らない場合は、a を式に強制することはできないと思います。

API 設計で Mockito の例に従うことができます。通常、次のようなモックを設定します。

when(mockedInstance.someMethod()).thenThrow(new IllegalArgumentException());

しかし、ボイドの場合は、次のようにします。

doThrow(new IllegalArgumentException()).when(mockedInstance).someMethod();

同様に、メソッドを列挙しEffect<T>てライブラリの静的メソッドにすることができます。

たとえば、Effect<T>持っている場合はdoSomething()、次のように反転します

doSomething().onEffectFor(proxyInstanceOfA).methodA();

Effect<T>ただし、これは、関連するメソッド自体が値を返さないことを前提としています。

それがオプションではなく、必要な場合は、次のEffect<T>ようにステートフルにすることができます。

VoidEffect<MyType> effect = effectForVoid(proxyOfMyClass);
effect.on().myVoidMethod();

どこでをVoidEffect<T>実装しEffect<Void>on()渡されたプロキシ (または別のプロキシ) を返します。次に、他の方法で とやり取りする前に、 if が呼び出されなかったIllegalStateException場合にスローする必要があります。on()effect

于 2012-08-27T05:11:54.423 に答える