PROPOSAL: Glue classes based on Extension Methods

Marek Kozieł develop4lasu at gmail.com
Mon Mar 30 23:27:46 PDT 2009


GENESIS
  I simplified glue classes and described it basing on Extension
Methods, but it still can be extended to support static / static
methods "ArrayList<String>..create();" and static variables. The main
difference rely on the way glue method is executed (almost no names
conflicts).
  I hope that this version will be easier to understood, especially
the way TypeParameters are split.

AUTHOR: Lasu aka Marek Kozieł

OVERVIEW

FEATURE SUMMARY:
Glue classes allow to execute static methods on objects using double
dot notation.


MAJOR ADVANTAGE:
Simplification of localizing additional functionality


MAJOR BENEFIT(s):
+ New functions can be easy localized (critically important during
introduction new people into project).
+ Security: glue class does not see anything protected.
+ Light binding new functionality with existing classes.
+ Reduction of a number of used classes.
+ It allows to assign methods and functions (static methods) to
arrays, classes, interfaces, …
+ It's proof against the situation that the same method occurs in
class and delegator as well as in two delegators.
+ It allows to link gained(.jar) logic with a new one, what is
impossible before final developer implements his classes.
+ It allows to project compact interfaces and does not worry about
additional logic.


MAJOR DISADVANTAGE:
 -



ALTERNATIVES:
Utils classes, more work on project, duplicated code...



EXAMPLES
SIMPLE / ADVANCED EXAMPLE:
See below.


DETAILS
SPECIFICATION:


Extension Methods:

public class Extensions{
    public static int countWords(this String str){
        return str.Split(...)...;
    }

    public static String[] split(this String str, boolean trim){
        return str.Split(...)...;
    }
}

To make it Glue class we extract type linked with 'this' to class
header, remove parameter name occurring after 'this', remove static
word, and use 'this' as simple parameter:

public class base glue (String ){
    public int countWords(this){
        return this.split(...)...;
    }

    public String[] split(this, boolean trim){
        return this.split(...)...;
    }

}


How do we execute methods:

Extension Methods:
        int count = “Extension Methods”.countWords();

Glue classes:
base is in import and no other glue method exists with same name for
this object:
        int count = “Extension Methods”..countWords();

or
base is in import:
        int count = “Extension Methods”..base.countWords();

or
        int count = “Extension Methods”..com.some.base.countWords();





GENERICS:

Extension Methods:
    public class Extensions{
        public static <T> T getLast(this ArrayList<T> list){
            return list.get(list.size()-1);
        }

        public static <T> T getFirstValid(this ArrayList<T> list,
Validator<? super T> validator){
            for (T t : list){
                if (validator.isValid(t)) return t;
            }
            return null;
        }

    }

Glue classes:
    public class base <T> glue ( ArrayList<T> ){
        public T getLast( this ){
            return list.get(list.size()-1);
        }

        public T getFirstValid( this , Validator<? super T> validator){
            for (T t : list){
                if (validator.isValid(t)) return t;
            }
            return null;
        }

    }

How do we execute methods (glue):
       void test(ArrayList<String> list){
              System.out.print(“Last:” + list..getLast() );
      }

Advanced:
    public class base <T> glue ( ArrayList<T> ){

        public <S> T getFirstValid( this , Validator<? super T,S>
validator, S condition){
            for (T t : list){
                if (validator.isValid( t, condition )) return t;
            }
            return null;
        }

    }
Execution:
       void test(ArrayList<String> list, Condition condition){
              System.out.print(“First:” +
list..<Condition>getFirstValid(Condition.validator, condition ) );
      }

Notice that T cannot be directly specified while it's always
determined by object used as 'this'


COMPILATION
  All methods are compiled to simple static form (like this visible in
extension methods:) , so they can be executed in normal way.
  The extracted method header (like: <T> glue (ArrayList<T>)) to class
header is used for grouping methods properly.
  Method: <T> $glue (ArrayList<T> nothing){}; is created basing on:
“<T> glue (ArrayList<T>)” and used for matching control and
determining which class is glue type.


TESTING:
Like simple static methods.

LIBRARY SUPPORT:
No.

REFLECTIVE APIS:
No.

OTHER CHANGES:
No.

MIGRATION:
None.

COMPATIBILITY
New jars are fully compatible. Code is only backward compatible.

REFERENCES:
http://msdn.microsoft.com/en-us/library/bb383977.aspx

http://bugs.sun.com/view_bug.do?bug_id=4093687

http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000680.html



More information about the coin-dev mailing list