aboutsummaryrefslogtreecommitdiffstats
path: root/docs/adk15ProgGuideDB/covariance.xml
diff options
context:
space:
mode:
authoracolyer <acolyer>2004-11-24 19:57:59 +0000
committeracolyer <acolyer>2004-11-24 19:57:59 +0000
commitacbb4e5b1a7c107d0f3897431b15a78d9026c381 (patch)
tree27bace6b8184de939ece3f89b6c354a31aa97a94 /docs/adk15ProgGuideDB/covariance.xml
parent639b61b6a7f5cd090137340c35c2f4ae355ad538 (diff)
downloadaspectj-acbb4e5b1a7c107d0f3897431b15a78d9026c381.tar.gz
aspectj-acbb4e5b1a7c107d0f3897431b15a78d9026c381.zip
more updates to 1.5 design
Diffstat (limited to 'docs/adk15ProgGuideDB/covariance.xml')
-rw-r--r--docs/adk15ProgGuideDB/covariance.xml174
1 files changed, 174 insertions, 0 deletions
diff --git a/docs/adk15ProgGuideDB/covariance.xml b/docs/adk15ProgGuideDB/covariance.xml
index d182e157e..4e1e2f8de 100644
--- a/docs/adk15ProgGuideDB/covariance.xml
+++ b/docs/adk15ProgGuideDB/covariance.xml
@@ -2,5 +2,179 @@
<title>Covariance</title>
+ <sect1 id="covariance-inJava5">
+ <title>Covariance in Java 5</title>
+
+ <para>
+ Java 5 (and hence AspectJ 1.5) allows you to narrow the return type
+ in an overriding method. For example:
+ </para>
+
+ <programlisting><![CDATA[
+ class A {
+ public A whoAreYou() {...}
+ }
+
+ class B extends A {
+ // override A.whoAreYou *and* narrow the return type.
+ public B whoAreYou() {...}
+ }
+ ]]></programlisting>
+
+ </sect1>
+
+ <sect1>
+ <title>Covariant methods and Join Point matching</title>
+
+ <para>The join point matching rules for <literal>call</literal>
+ and <literal>execution</literal> pointcut designators are extended
+ to match against covariant methods.</para>
+
+ <para>
+ Given the classes <literal>A</literal> and <literal>B</literal>
+ as defined in the previous section, and the program fragment
+ </para>
+
+ <programlisting><![CDATA[
+ A a = new A();
+ B b = new B();
+ a.whoAreYou();
+ b.whoAreYou();
+ ]]></programlisting>
+
+ <para>Then the call and execution join points for <literal>whoAreYou</literal>
+ are matched as follows:</para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term>call(* whoAreYou())</term>
+ <listitem>
+ <para>Matches both calls, (since it places no constraint on the
+ return type of the join point signature).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>call(* A.whoAreYou())</term>
+ <listitem>
+ <para>Matches both calls, (since the original declaring type
+ of <literal>whoAreYou</literal> is <literal>A</literal>).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>call(A whoAreYou())</term>
+ <listitem>
+ <para>Matches both calls, (since the signature of
+ <literal>whoAreYou</literal>) in the original declaring type
+ has a return type of <literal>A</literal>).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>call(A B.whoAreYou())</term>
+ <listitem>
+ <para>Does not match anything - the signature of <literal>whoAreYou</literal>
+ as overriden in <literal>B</literal> has a return type of
+ <literal>B</literal>, not <literal>A</literal>. A lint warning is
+ given for the call <literal>a.whoAreYou()</literal> ("does not match
+ because declaring type is A, if match required use target(B)").
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>call(A+ B.whoAreYou())</term>
+ <listitem>
+ <para>Matches the call to <literal>b.whoAreYou()</literal> since
+ the return type <literal>B</literal> in the method signature
+ is matched by the type pattern <literal>A+</literal>. A lint warning is
+ given for the call <literal>a.whoAreYou()</literal> ("does not match
+ because declaring type is A, if match required use target(B)").
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>call(B A.whoAreYou())</term>
+ <listitem>
+ <para>Does not match anything - there is no method declared in
+ <literal>A</literal> with a return type of <literal>B</literal>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>call(B whoAreYou())</term>
+ <listitem>
+ <para>Matches the call to <literal>b.whoAreYou()</literal> only.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>call(B B.whoAreYou())</term>
+ <listitem>
+ <para>Matches the call to <literal>b.whoAreYou()</literal> only.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ <para>The rule for signature matching at call and execution join points
+ is unchanged from AspectJ 1.2: a call or execution pointcut matches if
+ the signature pattern matches at least one of the signatures of the
+ join point, and if the most-specific matched signature is also matched
+ by any modifier pattern or annotation pattern that may be present.</para>
+
+ <para>For a call or execution join point, the signatures of a join point
+ for the call or execution of a method <literal>Rtype T.m(params)</literal>
+ are determined as follows:</para>
+ <itemizedlist>
+ <listitem>
+ If <literal>m(params)</literal> is defined in <literal>T</literal>,
+ then the signature of <literal>m(params)</literal> in <literal>T</literal> is
+ a signature of the join point: <literal>Rtype T.m(params)</literal>.
+ If <literal>T</literal> does not
+ provide its own definition of <literal>m</literal>, then the signature
+ <literal>Rtype' T.m(params)</literal>
+ is a signature of the join point, where <literal>Rtype'</literal> is the return type of
+ the definition of <literal>m</literal> inherited by <literal>T</literal>.
+ </listitem>
+ <listitem>
+ For each super-type <literal>S</literal> of <literal>T</literal> that is a valid receiver
+ for a call to <literal>m</literal>, then the signature of <literal>m(params)</literal> in
+ <literal>S</literal> is a signature
+ of the join point: <literal>Rtype S.m(params)</literal>.
+ If <literal>S</literal> does not provide its
+ own definition of <literal>m</literal>, then the signature
+ <literal>Rtype' S.m(params)</literal> is a
+ signature of the join point, where <literal>Rtype'</literal> is the return type of the
+ definition of <literal>m</literal> inherited by <literal>S</literal>.
+ </listitem>
+ </itemizedlist>
+
+ <para>A call to <literal>b.whoAreYou()</literal> has the join point signatures
+ </para>
+
+ <itemizedlist>
+ <listitem>B B.whoAreYou()</listitem>
+ <listitem>A A.whoAreYou()</listitem>
+ </itemizedlist>
+
+ <para>Following the rule given, it is easy to see why for example
+ <literal>call(B A.whoAreYou())</literal> does not match anything as
+ this pattern matches neither of the signatures at the join point. In
+ contrast, the pointcut expression <literal>call(A+ B.whoAreYou())</literal>
+ does match the call to <literal>b.whoAreYou()</literal> because it matches
+ the second of the signatures at the join point.</para>
+ </sect1>
+
+
</chapter>