getを呼び出すたびに呼び出されるメソッドを定義する方法はありますか?
オブジェクトの連絡先があり、updateLastUsed();を設定したくありません。私のメンバーのための約30ゲッターで。
プロパティのゲッターにアクセスする代わりに、プロパティ名を入力として受け取る一般的なゲッターを 1 つ作成できます。プロパティの型が異なる場合、戻り値の型は Object である必要があります。
この一般的な getter では、プロパティ getter と updateLastUsed() メソッドを呼び出します。安全のために、すべてのプロパティ ゲッターを非公開にしてください。
すべてのメソッドへの呼び出しを追加する(退屈な)か、何らかの形式のAOP(たとえば、以下の例ではAspectJ)を使用して、型のゲッターと一致させ、updateLastUsed()メソッドを呼び出すことができます。
編集:何人かの人々は、30のゲッターはコードの臭いであり、別のメソッドを呼び出すことは副作用であると指摘しています。最初のステートメントは公正な指標ですが、ルールではありません。この種のタイプを使用する理由はたくさんありますが、それ以上の情報がなければ、責任を2つ以上のタイプに分けることができるかどうかを確認するためのアドバイスとして残しておきます。
副作用に関する他のポイントは、関連する場合と関連しない場合があります。ゲッターメソッドに適用するのが賢明な横断的関心事はたくさんあります。たとえば、ロギング、認証、キャッシング。サンプルメソッドupdateLastUsed()はキャッシング戦略の一部である可能性があるため、私の意見では、この質問に対する無条件の批判は当然のことです。
AspectJでポイントカットとアドバイスを実装する方法の例は次のとおりです。
package test;
public aspect TestAspect {
/**
* Match all getters of test.Contact and bind the target.
*/
protected pointcut contactGetters(Contact contact) :
execution(* test.Contact.get*()) && target(contact);
/**
* Before execution of each getter, invoke the updateLastUsed() method
* of the bound target.
*/
before(Contact contact): contactGetters(contact) {
contact.updateLastUsed();
}
}
AOPを提案したと思いますが、J2MEの場合は、30個のアクセサーのそれぞれに手動で「onGetCalled()」を挿入し、そのメソッド内で必要なものをコーディングする方がよいでしょう。将来必要になった場合に備えて、呼び出されている(またはアクセスされているプロパティ)メソッドの名前を渡すことをお勧めします。
これはアスペクト指向プログラミング(AOP)の仕事のように見えます。
で始まるものすべてに対して実行されるアスペクトを定義するget*
「新しい」AspectJ5は、アノテーションを使用してアスペクトポイントカットを定義することをサポートしているため@Before
、メソッドの本体を実行するポイントカットを呼び出すようにゲッターにアノテーションを付けることができます。
これを行うには、AOPのようなものが必要になります。これ以外のJ2MEでどれだけサポートされているかわかりません。
java.lang.reflect.Proxy
AOPの他に、またはバイトコード操作を使用できます。
しかし、J2MEではありません
updateLastUsed()を30回呼び出すことをお勧めします。
正規表現を使用して、メソッド呼び出しを getter ヘッダーに追加します。
探す:
\w+ get\w+\s*\(\)\s*\{(\s*)
と置換する:
\0updateLastUsed();\1
これらの式は、[検索/置換] ダイアログの [すべて置換] を使用して Eclipse 3.5 (Galileo) を使用してテストされました。
使用するエディターが複数行の一致をサポートしている (または有効にする必要がある) 必要があることに注意してください。EmEditor 8.05 では、検索文字列を次のように変更する必要がありました。
\w+ get\w+\s*\(\)\s*\{\s*(\n\s*)
新しい行が明示的に一致するようにします。置換文字列はそのまま残ります。
ここに方法があります。きれいではありませんが、繰り返しよりも好むかもしれません。
public class GetterTest extends TestCase {
private static class Thing {
public int accessCount;
private String name;
private int age;
private <T> T get(T t) {
accessCount++;
return t;
}
public String getName() {
return get(name);
}
public int getAge() {
return get(age);
}
}
public void testGetIncrementsAccessCount() throws Exception {
Thing t = new Thing();
assertEquals(0, t.accessCount);
t.getName();
assertEquals(1, t.accessCount);
t.getAge();
assertEquals(2, t.accessCount);
}
}
明らかに、私の get() は accessCount をインクリメントしているだけであり、他の動作が必要になるでしょうが、アイデアはそこにあります。
何か凝ったことをすることもできますが、正直なところ、退屈なコードをすばやく繰り返すことができるように、エディターにマクロが追加されたのはそのためです。
すべてのゲッターによって呼び出されるメソッドを作成し、マクロを使用して呼び出しを作成します (メソッドごとに異なる必要がある場合)。これはすべて一度だけ行う必要があり、その後は忘れてしまいます...
オブジェクトをプロキシして、目的のメソッドを呼び出すと言います。