aboutsummaryrefslogtreecommitdiffstats
path: root/docs/adk15ProgGuideDB/covariance.xml
blob: b6b0d7e70572e86800189538c2efa576d4c34e06 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
<chapter id="covariance" xreflabel="Covariance">

  <title>Covariance</title>
  
      <sect1 id="covariance-inJava5">
        <title>Covariance in Java 5</title>
        
        <para>
          Java 5 (and hence AspectJ 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>The signatures for the call join point <literal>a.whoAreYou()</literal> are
		simply:</para>

		<programlisting><![CDATA[
		A A.whoAreYou()
		]]></programlisting>
		
		<para>The signatures for the call join point <literal>b.whoAreYou()</literal> are:
		</para>

		<programlisting><![CDATA[
		A A.whoAreYou()
		B B.whoAreYou()
		]]></programlisting>
		
		<para>Following the join point matching rules given in <xref linkend="jpsigs"/>,</para>
		
		<variablelist>

        <varlistentry>
          <term>call(* whoAreYou())</term>
          <listitem>
            <para>Matches both calls, (since each call join point has at least
            one matching signature).
            </para>
          </listitem>
        </varlistentry>

        <varlistentry>
          <term>call(* A.whoAreYou())</term>
          <listitem>
            <para>Matches both calls, (since each call join point has at least
            one matching signature).
            </para>
          </listitem>
        </varlistentry>

        <varlistentry>
          <term>call(A whoAreYou())</term>
          <listitem>
            <para>Matches both calls, (since each call join point has at least
            one matching signature).
            </para>
          </listitem>
        </varlistentry>
		
        <varlistentry>
          <term>call(A B.whoAreYou())</term>
          <listitem>
            <para>Does not match anything - neither of the call join points
            has a signature matched by this pattern.  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 signature pattern matches the signature <literal>B B.whoAreYou()</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 since neither join point has a 
            signature matched by this pattern.
            </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 modifiers of the method or constructor are matched
		by any modifier pattern or annotation pattern that may be present.</para>
		
		</sect1>
</chapter>