Adding New Affixes
Multiple affixes can be applied to a method independently of each other. That is to say that repeated calls to
AddPrefix, AddSuffix, AddWrapper
and AddSymmetricWrapper will simply add new affixes, irrespective of
any existing prefixes or suffixes that may be associated with the interceptee in question.
Note that a new prefix (added using AddPrefix, AddWrapper or
AddSymmetricWrapper) will be added such that it is the last to execute
in any existing set that is associated with the interceptee. Similarly, addition of a new suffix (added using AddSuffix,
AddWrapper or AddSymmetricWrapper) will cause it to execute before any
other suffixes that may be associated with the interceptee.
The example illustrates this by applying a prefix and a suffix to MyFunc, which is then invoked. A further
prefix and suffix are then added, before MyFunc is invoked a second time. The result is that the original
prefix executes first, followed by the new prefix, and then MyFunc, after
which the new suffix executes followed finally by the original suffix.
// Example 25
// Will not work with AJS_HP
function Prefix_0 () { alert ("Prefix_0 executed"); }
function Prefix_1 () { alert ("Prefix_1 executed"); }
function Suffix_0 () { alert ("Suffix_0 executed"); }
function Suffix_1 () { alert ("Suffix_1 executed"); }
function MyFunc () { alert ("MyFunc executed"); }
AJS.AddPrefix (this, "MyFunc", Prefix_0);
AJS.AddSuffix (this, "MyFunc", Suffix_0);
MyFunc ();
AJS.AddPrefix (this, "MyFunc", Prefix_1);
AJS.AddSuffix (this, "MyFunc", Suffix_1);
MyFunc ();
--------------------------------------
Output (using AJS):
Prefix_0 executed
MyFunc executed
Suffix_0 executed
Prefix_0 executed
Prefix_1 executed
MyFunc executed
Suffix_1 executed
Suffix_0 executed
Using AddBefore/AddAfter
If a given interceptee has a set of affixes, there will be times when a new prefix or suffix will be required to execute at a specific point
in the affix calling-order in that set. In other words, the default behaviour of AddPrefix etc, where
new affixes are added such that they are 'closest' temporally to the interceptee, may not be sufficient.
To address this situation, use the AddBefore and AddAfter methods of
the affix type. These methods create a new Affix object, insert it into the relevant set, take care of all
other book-keeping, and return a reference to the Affix object that has just been created. That object
permits insertion of further prefixes or suffixes, again through the use of
the AddBefore and AddAfter methods that it supports.
AddBefore applies the affix function, such that (on a call to the interceptee) it executes before the
affix on which AddBefore was called.
Conversely, AddAfter applies the affix function, such that it will execute after the affix on which AddAfter
was called. The diagram illustrates these two points.
Example Twenty-Six demonstrates the use of AddBefore and
AddAfter, using the Affix
object returned from a call to AddPrefix.
// Example 26
// Will work only in part with AJS_HP,
// but no exceptions will be raised
function Prefix_0 () { alert ("Prefix_0 executed"); }
function Prefix_1 () { alert ("Prefix_1 executed"); }
function Prefix_2 () { alert ("Prefix_2 executed"); }
function MyFunc () { alert ("MyFunc executed"); }
var PrefixObj = AJS.AddPrefix (this, "MyFunc", Prefix_1);
PrefixObj.AddAfter (Prefix_2);
MyFunc ();
PrefixObj.AddBefore (Prefix_0);
MyFunc ();
--------------------------------------
Output (using AJS):
Prefix_1 executed
Prefix_2 executed
MyFunc executed
Prefix_0 executed
Prefix_1 executed
Prefix_2 executed
MyFunc executed
The next example demonstrates the application of a third prefix-function, through the AddAfter
method of the Affix object returned from a previous call to AddAfter.
// Example 27
// Will work only in part with AJS_HP
function Prefix_0 () { alert ("Prefix_0 executed"); }
function Prefix_1 () { alert ("Prefix_1 executed"); }
function Prefix_2 () { alert ("Prefix_2 executed"); }
function MyFunc () { alert ("MyFunc executed"); }
var PrefixObj = AJS.AddPrefix (this, "MyFunc", Prefix_0);
PrefixObj = PrefixObj.AddAfter (Prefix_1);
PrefixObj.AddAfter (Prefix_2);
MyFunc ();
--------------------------------------
Output (using AJS):
Prefix_0 executed
Prefix_1 executed
Prefix_2 executed
MyFunc executed
Note that where a prefix and suffix have been attached using AddWrapper or AddSymmetricWrapper,
adding new prefixes and suffixes operates in exactly the same way as described above. Example Twenty-Eight illustrates this.
Note also that a given function can be attached an unlimited number of times to the same interceptee, thus allowing it to act as a number of
prefixes, suffixes, or prefixes and suffixes.
// Example 28
// Will work only in part with AJS_HP
function Prefix () { alert ("Prefix executed"); }
function Suffix_0 () { alert ("Suffix_0 executed"); }
function Suffix_1 () { alert ("Suffix_1 executed"); }
function MyFunc () { alert ("MyFunc executed"); }
var Wrapper = AJS.AddWrapper (this, "MyFunc", Prefix, "", Infinity, Suffix_0);
MyFunc ();
Wrapper.Suffix.AddAfter (Suffix_1);
MyFunc ();
--------------------------------------
Output (using AJS):
Prefix executed
MyFunc executed
Suffix_0 executed
Prefix executed
MyFunc executed
Suffix_0 executed
Suffix_1 executed
Multiple Affix Function-Signatures
Where more than one prefix or suffix is attached to an interceptee, more parameters are passed to the relevant
functions than when only a single affix is involved.
In the case of prefixes, these
are passed the same two arguments that single prefixes receive, but they also receive the return value of the
previous prefix. This permits 'prefix decoration' (in the Design Patterns sense), and thereby allows prefix
functionality to be built up in an additive fashion. Example Twenty-Nine illustrates this principle by means of
concatenating strings.
Note that if a prefix has no previous sibling then the value for the PrevPrefixResult argument is undefined,
as it must always be with single prefixes, and with the first prefix in a set of such functions.
// Example 29
// Will work only in part with AJS_HP
function Prefix_0 (Arg, PrevResult) { return "The rain "; }
function Prefix_1 (Arg, PrevResult) { return PrevResult + "in Spain "; }
function Prefix_2 (Arg, PrevResult) { return PrevResult + "falls "; }
function Prefix_3 (Arg, PrevResult) { return PrevResult + "mainly in "; }
function Prefix_4 (Arg, PrevResult) { return PrevResult + "the plain"; }
function Prefix_5 (Arg, PrevResult) { alert (PrevResult); }
function MyFunc () { alert ("MyFunc executed"); }
var PrefixObj = AJS.AddPrefix (this, "MyFunc", Prefix_5);
PrefixObj.AddBefore (Prefix_0);
PrefixObj.AddBefore (Prefix_1);
PrefixObj.AddBefore (Prefix_2);
PrefixObj.AddBefore (Prefix_3);
PrefixObj.AddBefore (Prefix_4);
MyFunc ();
--------------------------------------
Output (using AJS):
The rain in Spain falls mainly in the plain
MyFunc executed
In the case of suffixes, these are passed the same three leading-arguments that single suffixes receive, plus they
receive the return value of the previous suffix. As with prefixes, this allows decoration of suffix functionality,
and Example Thirty shows this principle, also by means of the concatenation of strings.
As with prefixes, suffixes that have no previous sibling receive a value of undefined
for the PrevSuffixResult
argument.
// Example 30
// Will work only in part with AJS_HP
// Note: IArgs, and IResult denote 'Interceptee Arguments'
// and 'Interceptee Result' respectively
function Suffix_0 (Arg, PrevResult, IArgs, IResult) { return IResult + "sticks, "; }
function Suffix_1 (Arg, PrevResult, IArgs, IResult) { return PrevResult
+ IResult + " wax, "; }
function Suffix_2 (Arg, PrevResult, IArgs, IResult) { return PrevResult
+ IResult + "light "; }
function Suffix_3 (Arg, PrevResult, IArgs, IResult) { alert (PrevResult
+ "all relate to "
+ IResult + "s"); }
function MyFunc ()
{
alert ("Returning 'Candle'");
return "Candle";
}
var SuffixObj = AJS.AddSuffix (this, "MyFunc", Suffix_3);
SuffixObj.AddBefore (Suffix_0);
SuffixObj.AddBefore (Suffix_1);
SuffixObj.AddBefore (Suffix_2);
MyFunc ();
--------------------------------------
Output (using AJS):
Returning 'Candle'
Candlesticks, Candle wax, Candlelight all relate to Candles.
Go forward to
Part 7 of this tutorial.
Go back to
Part 5 of this tutorial.
Copyright © Dodeca Technologies Ltd. 2007