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