Polymorphic copy: Difference between revisions
(added ocaml) |
(added python) |
||
Line 101: | Line 101: | ||
method name = "S" |
method name = "S" |
||
end |
end |
||
let copier = Oo.copy |
|||
let () = |
let () = |
||
print_endline ( |
print_endline (Oo.copy obj1)#name; (* prints "T" *) |
||
print_endline ( |
print_endline (Oo.copy obj2)#name; (* prints "S" *)</ocaml> |
||
=={{header|Python}}== |
|||
<python>import copy |
|||
class T: |
|||
def name(self): return "T" |
|||
class S: |
|||
def name(self): return "S" |
|||
obj1 = T() |
|||
obj2 = S() |
|||
print copy.copy(obj1).name() # prints "T" |
|||
print copy.copy(obj2).name() # prints "S"</python> |
Revision as of 21:37, 25 October 2008
![Task](http://static.miraheze.org/rosettacodewiki/thumb/b/ba/Rcode-button-task-crushed.png/64px-Rcode-button-task-crushed.png)
You are encouraged to solve this task according to the task description, using any language you may know.
An object is polymorphic when its specific type may vary. The types a specific value may take, is called class.
It is trivial to copy an object if its type is known: <c> int x; int y = x; </c> Here x is not polymorphic, so y is declared of same type (int) as x. But if the specific type of x were unknown, then y could not be declared of any specific type.
The task: let a polymorphic object contain an instance of some specific type S derived from a type T. The type T is known. The type S is possibly unknown until run time. The objective is to create an exact copy of such polymorphic object (not to create a reference, nor a pointer to). Let further the type T have a method overridden by S. This method is to be called on the copy to demonstrate that the specific type of the copy is indeed S.
Ada
<ada> with Ada.Text_IO; use Ada.Text_IO;
procedure Test_Polymorphic_Copy is
package Base is type T is tagged null record; function Name (X : T) return String; end Base; use Base; package body Base is function Name (X : T) return String is begin return "T"; end Name; end Base; -- The procedure knows nothing about S procedure Copier (X : T'Class) is Duplicate : T'Class := X; -- A copy of X begin Put_Line ("Copied " & Duplicate.Name); -- Check the copy end Copier;
package Derived is type S is new T with null record; overriding function Name (X : S) return String; end Derived; use Derived; package body Derived is function Name (X : S) return String is begin return "S"; end Name; end Derived;
Object_1 : T; Object_2 : S;
begin
Copier (Object_1); Copier (Object_2);
end Test_Polymorphic_Copy; </ada> The procedure Copier does not know the specific type of its argument. Nevertheless it creates an object Duplicate of exactly same type. Sample output:
Copied T Copied S
Java
Here we implement a "copy" method once in the base class because there is by default no public way to copy an object from outside the class in Java. (There is a protected, not public, "clone" method inherited from Object.) <java>class T implements Cloneable {
public String name() { return "T"; } public T copy() { try { return (T)super.clone(); } catch (CloneNotSupportedException e) { return null; } }
}
class S extends T {
public String name() { return "S"; }
}
public class PolymorphicCopy {
public static T copier(T x) { return x.copy(); } public static void main(String[] args) { T obj1 = new T(); S obj2 = new S(); System.out.println(copier(obj1).name()); // prints "T" System.out.println(copier(obj2).name()); // prints "S" }
}</java>
OCaml
I decided not to use classes and inheritance here because structural subtyping is more natural in OCaml. Oo.copy is polymorphic over all object types. <ocaml>let obj1 =
object method name = "T" end
let obj2 =
object method name = "S" end
let () =
print_endline (Oo.copy obj1)#name; (* prints "T" *) print_endline (Oo.copy obj2)#name; (* prints "S" *)</ocaml>
Python
<python>import copy
class T:
def name(self): return "T"
class S:
def name(self): return "S"
obj1 = T() obj2 = S() print copy.copy(obj1).name() # prints "T" print copy.copy(obj2).name() # prints "S"</python>