Cloneable

For an actual type parameter Person this factory generates a class CloneablePerson that extends class Person. CloneablePerson has a public clone() method that returns an object that is a shallow clone of the object on which it is called.

It would be easy to generate a method performing a deep clone, if every object would be guaranteed to have a method clone(). Then this clone method could be invoked for every class type attribute so that the clone could be delegated to all associated objects. Unfortunately, the clone() member method of the Java root class Object has protected access, so that it can only be accessed by objects of the same package. Consequently, not every class can access clone() and a recursive deep clone does not work.

Note that the factory works only for actual parameters that do not declare private attributes. The factory would generate code that would try to access these private attributes, and because Java forbids subclasses to access the private attributes of its superclasses and the generated class is a subclass of the actual type parameter this could not be compiled.

Factory/Java Source

The source can be found in the Factory/Java .zip-archive in factory/classes/examples/Cloneable.factory:

<param> <var> T </var> </param>

package test;

public class
<apply>
    <const> "Cloneable" </const>
    <method> concat </method>
    <args>
        <apply>
            <class> factory.Toolbox </class>
            <method> getRelativeName </method>
            <args>
                <var> T </var>
            </args>
        </apply>
    </args>
</apply>
extends <var> T </var>
implements Cloneable
{                    
    public Object clone() {
        Object o = null;
        try {
            o = this.getClass().newInstance();
        } catch(Exception e) {
            System.out.println(e);
        }
        
        <var> T </var> a = (<var> T </var>) o;
        
        // iterate over all attributes of T
        <for> <var> I </var>
        <apply>
            <class> factory.Toolbox </class>
            <method> getAllFields </method>
            <args> <var> T </var> </args>
        </apply>
        <body>
            <let> <var> FN </var>
            <apply>
                <var> I </var> <method> getName </method>
            </apply>
            <body>
                a.<var> FN </var> = this.<var> FN </var>;
            </body> </let>
        </body> </for>
        
        return a;
    }
}

Test Program

The following unparameterized factory can be found in factory/src/test/CloneableTest.factory in the Factory .zip-archive. It applies factory Cloneable to class Person, instantiates an object of the resulting class CloneablePerson, sets some of its attributes to arbitrary values, calls its clone() method and prints out the attributes of the resulting clone-object.

package test;

public class CloneableTest {
    public static void main(String argv[]) {
        <let> <var> T </var>
        <apply>
            <factory> examples/Cloneable </factory>
            <args> <const> test.Person </const> </args>
        </apply>
        <body>
            <var> T </var> a = new <var> T </var>();

            a.name = "Mr.X";
            a.plz = 4711;
            a.id = 1;
       
            <var> T </var> b = (<var> T </var>) a.clone();
       
            System.out.println(b.name);
            System.out.println(b.plz);
            System.out.println(b.id);
        </body> </let>
    }
}

This factory can be compiled in the factory directory with
java -classpath classes factory.Factory -javad src -classd classes src/test/CloneableTest
and run with
java -classpath classes test.CloneableTest