Polymorphic copy: Difference between revisions

From Rosetta Code
Content added Content deleted
(added java)
(added ocaml)
Line 89: Line 89:
}
}
}</java>
}</java>

=={{header|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 copier = Oo.copy

let () =
print_endline (copier obj1)#name; (* prints "T" *)
print_endline (copier obj2)#name; (* prints "S" *)</ocaml>

Revision as of 21:28, 25 October 2008

Task
Polymorphic copy
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 copier = Oo.copy

let () =

 print_endline (copier obj1)#name; (* prints "T" *)
 print_endline (copier obj2)#name; (* prints "S" *)</ocaml>