Aspectual Overriding

AOP の特徴の一つは、メソッドの呼び出しなどのインターセプトができること。オーバーライドは、継承する側が継承される側のメソッドを同じシグネチャを元にして書き換えること(正確な定義は知らない)。


そう、この二つ(インターセプトとオーバーライド)の関係は?


たとえば以下のような Component クラスがあったとする:


public class Component {

public void method() {
System.out.println("Component.method()");
}
}

この Component クラスの method() メソッドをインターセプト(あるいは、around アドバイス)する例としては、AspectJでは以下のように書ける:

public aspect ComponentAspect {

void around() : call( void Component.method() ) {
System.out.println("ComponentAspect");
}
}

AspectJ では、アドバイスには名前が無いので例えば以下のようには書けない:

public aspect ComponentAspect {

void around method() : call( void Component.method() ) {
System.out.println("ComponentAspect");
}
}

逆に、アドバイスに名前があると、method() の部分が重複するので多少名前を考えるのがめんどくさい。


では、以下のように書くのは?


public aspect ComponentAspect {

public void Component.method() {
System.out.println("ComponentAspect");
}
}

AspectJ では、これは inter-type declaration として扱われるのでコンパイル時にエラー。


しかし、もし、これはエラーではなくてオーバーライド(あるいは around アドバイス)と同じ効果を持つとしたら? この場合は、もし、アスペクト側の行いたいことが、スタティックなオーバーライドであるのであれば、望みの通り。でも、そうではなく、ダイナミックなオーバーライドであるのであれば、望みは達成されない。


ここでいうダイナミックとは、もし、アスペクトの機能(アドバイス)がオンやオフに実行時にできると仮定すると、そのアスペクトがオンの時には、オーバーライドとなって欲しくて、オフの時には、オーバーライドとなって欲しくない、という意味。