Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| research:mao:parametric-polymorphism [2012/01/10 15:23] – minostro | research:mao:parametric-polymorphism [2012/08/22 00:30] (current) – [StrongAspectJ in action] minostro | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | ====== Parametric Polymorphism ====== | ||
| + | FIXME | ||
| + | * Introduction | ||
| + | * StrongAspectJ in action | ||
| + | * How StrongAspectJ fails with ranges types and interfaces. | ||
| + | * How parametric return and arguments types can ensure generic advice definition. | ||
| + | * Examples | ||
| + | |||
| + | |||
| + | ====== Introduction ====== | ||
| + | |||
| + | We need to introduce Type Variables and Parameterized Type Declarations in order to implement parametric polymorphism in our jpi abc compiler extension. | ||
| + | |||
| + | * jpi type declarations | ||
| + | * exhibits clause | ||
| + | * advice declarations | ||
| + | |||
| + | With parametric polymorphism we can write generic aspects without burdening programmers with the current verbosity of our approach. | ||
| + | |||
| + | Consider the implementation of the logger cross-cutting concern with the following base code: | ||
| + | |||
| + | <code java> | ||
| + | class C{ | ||
| + | void foo(){...} | ||
| + | | ||
| + | float zoo(C a){...} | ||
| + | | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | The implementation of Logger is pretty straightforward using a plain AspectJ aspect: | ||
| + | |||
| + | <code java> | ||
| + | aspect Logger{ | ||
| + | | ||
| + | /* do something before */ | ||
| + | return proceed(); | ||
| + | /* do something after */ | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Conversely, the implementation of Logger using a JPI aspect is pretty verbose which force programmers to declare for each different join point one jpi definition. | ||
| + | |||
| + | <code java> | ||
| + | jpi void MyJPI(); | ||
| + | jpi Integer MyJPIInteger(); | ||
| + | jpi float MyJPIFloat(); | ||
| + | |||
| + | class C{ | ||
| + | |||
| + | | ||
| + | | ||
| + | | ||
| + | |||
| + | void foo(){...} | ||
| + | | ||
| + | float zoo(C a){...} | ||
| + | | ||
| + | } | ||
| + | |||
| + | aspect Logger{ | ||
| + | void around MyJPI(){ | ||
| + | /* do something before */ | ||
| + | proceed(); | ||
| + | /* do something after */ | ||
| + | } | ||
| + | |||
| + | void around MyJPIInteger(){ | ||
| + | /* do something before */ | ||
| + | return proceed(); | ||
| + | /* do something after */ | ||
| + | } | ||
| + | |||
| + | void around MyJPIFloat(){ | ||
| + | /* do something before */ | ||
| + | return proceed(); | ||
| + | /* do something after */ | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | With parametric polymorphism, | ||
| + | |||
| + | <code java> | ||
| + | jpi <T> T MyJPI(); | ||
| + | |||
| + | class C{ | ||
| + | |||
| + | | ||
| + | |||
| + | void foo(){...} | ||
| + | | ||
| + | float zoo(C a){...} | ||
| + | | ||
| + | } | ||
| + | |||
| + | aspect Logger{ | ||
| + | < | ||
| + | /* do something before */ | ||
| + | return proceed(); | ||
| + | /* do something after */ | ||
| + | } | ||
| + | } | ||
| + | |||
| + | </ | ||
| + | |||
| + | Due that current version of abc compiler does not support Generics, we need to define new typing rules for each expression on which a Type Variable or a Parameterized Typed Declaration is involved. | ||
| + | |||
| + | ====== StrongAspectJ in action====== | ||
| + | |||
| + | <code java> | ||
| + | aspect Logger { | ||
| + | |||
| + | Integer around(Person p): | ||
| + | call(Integer *(..)) && args(p): | ||
| + | Integer proceed(Clerk){ | ||
| + | System.out.println(p.getName()); | ||
| + | return proceed(new Clerk()); | ||
| + | //return proceed(p) <-- [aspects.Person] do not match [aspects.Clerk] | ||
| + | } | ||
| + | |||
| + | // AspectJ around advice definition | ||
| + | /* | ||
| + | Integer around(Person p): | ||
| + | call(Integer *(..)) && args(p){ | ||
| + | System.out.println(p.getName()); | ||
| + | return proceed(p); | ||
| + | } | ||
| + | */ | ||
| + | |||
| + | public static void main(String[] args){ | ||
| + | Clerk c = new Clerk(); | ||
| + | Employee e = new Employee(); | ||
| + | Person p = new Person(); | ||
| + | register(c); | ||
| + | register(e); | ||
| + | register(p); | ||
| + | } | ||
| + | |||
| + | public static Integer register(Person e){ | ||
| + | System.out.println(e.getName()+" | ||
| + | return new Integer(2); | ||
| + | } | ||
| + | |||
| + | } | ||
| + | </ | ||
| + | |||
| + | б< | ||
| + | |||
| + | Clerk --> Integer ≤ б< | ||
| + | |||
| + | pc = (Clerk - Person) --> Integer - Integer | ||
| + | |||
| + | pc< | ||
| + | |||
| + | pc< | ||
| + | |||
| + | б< | ||
| + | |||
| + | You mIght notice that proceed invocation does not be accomplished using the same value of the advice argument. | ||
| + | |||
| + | ===== Multiple path issue ===== | ||
| + | |||
| + | |||
| + | Despite double around advice signature, it is possible get weaving time errors in StrongAspectJ. | ||
| + | |||
| + | <code java> | ||
| + | interface Item{ | ||
| + | String foo(); | ||
| + | } | ||
| + | |||
| + | class EcoFriendly implements Item{ | ||
| + | public String foo() { | ||
| + | System.out.println(" | ||
| + | return " | ||
| + | } | ||
| + | } | ||
| + | |||
| + | class BestSeller implements Item{ | ||
| + | public String foo() { | ||
| + | System.out.println(" | ||
| + | return " | ||
| + | } | ||
| + | } | ||
| + | | ||
| + | public aspect example { | ||
| + | String around(Object ef) : | ||
| + | target(ef) && call(String foo(..)): | ||
| + | String proceed(Item){ | ||
| + | return proceed(new BestSeller(){}); | ||
| + | } | ||
| + | |||
| + | public static void main(String[] args){ | ||
| + | EcoFriendly b = new EcoFriendly(); | ||
| + | b.foo(); | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | The output is the following: | ||
| + | |||
| + | < | ||
| + | Exception in thread " | ||
| + | at example.inline$0$around$0(example.java: | ||
| + | at example.main(example.java: | ||
| + | </ | ||
| + | |||
| + | When a interface type is used in both sides of type ranges, StrongAspectJ raises a huge traceback exception indicating that there is a polyglot.util.InternalCompileError. | ||
| + | ====== References ====== | ||
| + | |||
| + | [1] Gilad Bracha, Martin Odersky, David Stoutamire, and Philip Wadler. **GJ Specification** Manuscript, May 1998. | ||
| + | |||
| + | [2] B. De Fraine, M. Südholt, and V. Jonckers. | ||

