Jump to content

Object copying: Difference between revisions

From Wikipedia, the free encyclopedia
Content deleted Content added
No edit summary
m Links: decapitalized non-proper nouns, removed needless piping. Headings: removed words duplicating parent heading. Sequence alphabetized. Minor copy edits. Inline references: made from bare URLs.
Line 1: Line 1:
One of the most common procedures that occurs in computer programs is the copying of data. An [[object (computer science)|object]] is a composite [[data type]] in [[object-oriented programming]] languages. '''Object copy''' thus describes the action wherein an object has its [[Attribute (computing)|attributes]] copied to another object of the same data type. An object may be copied in order to reuse all or part of its data in a new context.
One of the most common procedures that occurs in computer programs is the copying of data. An [[object (computer science)|object]] is a composite [[data type]] in [[object-oriented programming]] languages. '''Object copy''' thus describes the action wherein an object has its [[attribute (computing)|attributes]] copied to another object of the same data type. An object may be copied to reuse all or part of its data in a new context.


== Deep vs. Shallow vs. Lazy copy ==
== Deep vs. Shallow vs. Lazy copy ==
Line 5: Line 5:
The design goal of most objects is to give the semblance of being made out of one monolithic block even though most are not. As objects are made up of several different parts, copying becomes non trivial. Several strategies exist to attack this problem.
The design goal of most objects is to give the semblance of being made out of one monolithic block even though most are not. As objects are made up of several different parts, copying becomes non trivial. Several strategies exist to attack this problem.


Consider two objects, A and B, which each [[Reference (computer science)|refer]] to two memory blocks x<sub>i</sub> and y<sub>i</sub> (i = 1, 2,...). Think of A and B as strings and of x<sub>i</sub> and y<sub>i</sub> (i = 1, 2,...) as the characters they contain.
Consider two objects, A and B, which each [[reference (computer science)|refer]] to two memory blocks x<sub>i</sub> and y<sub>i</sub> (i = 1, 2,...). Think of A and B as strings and of x<sub>i</sub> and y<sub>i</sub> (i = 1, 2,...) as the characters they contain.


[[Image:Pre shallow deep copy.svg|400px]]
[[Image:Pre shallow deep copy.svg|400px]]
Line 19: Line 19:
[[Image:shallow copy done.svg|400px]]
[[Image:shallow copy done.svg|400px]]


This results in a situation in which some data is shared between A and B, thus modifying the one will alter the other. The original memory block of B is now no longer referred to from anywhere. If the language does not have automatic [[Garbage collection (computer science)|garbage collection]] the original memory block of B has probably been [[Memory leak|leaked]].
This results in a situation in which some data is shared between A and B, thus modifying the one will alter the other. The original memory block of B is now no longer referred to from anywhere. If the language does not have automatic [[garbage collection (computer science)|garbage collection]] the original memory block of B has probably been [[memory leak|leaked]].


The advantage of shallow copies is that their execution speed is fast and does not depend on the size of the data.
The advantage of shallow copies is that their execution speed is fast and does not depend on the size of the data.
Line 45: Line 45:
== How to copy objects ==
== How to copy objects ==


Nearly all [[object oriented]] [[programming language]]s provide some way to copy objects. As the majority of languages do not provide most objects themselves, the programmer has to define how an object should be copied, just as he or she has to define if two objects are identical or even comparable in the first place. Many languages provide some default behavior.
Nearly all [[object-oriented]] [[programming language]]s provide some way to copy objects. As the majority of languages do not provide most objects themselves, the programmer has to define how an object should be copied, just as he or she has to define if two objects are identical or even comparable in the first place. Many languages provide some default behavior.


How copying is solved varies from language to language and what concept of an object it has. The following presents examples for two of the most widely used object-oriented languages, [[C++]] and [[Java (programming language)|Java]], which should cover nearly every way that an object-oriented language can attack this problem.
How copying is solved varies from language to language and what concept of an object it has. The following presents examples for two of the most widely used object-oriented languages, [[C++]] and [[Java (programming language)|Java]], which should cover nearly every way that an object-oriented language can attack this problem.


=== Copying in C++ ===
=== In C++ ===
{{main|copy constructor}}
{{main|copy constructor}}
C++ is designed so that user-defined types should be able to function exactly like native types such as '''char''' and '''int'''. One way in which C++ achieves this is by allowing any class to define a [[copy constructor]] and an assignment operator. C++ provides default versions of these which perform a memberwise copy, but any class is free to disable copying or define its own copy behaviour.
C++ is designed so that user-defined types should be able to function exactly like native types such as '''char''' and '''int'''. One way in which C++ achieves this is by allowing any class to define a [[copy constructor]] and an assignment operator. C++ provides default versions of these which perform a memberwise copy, but any class is free to disable copying or define its own copy behaviour.
Line 96: Line 96:
</source>
</source>


=== Another example of deep and shallow copying in C++ ===
==== Another example of deep and shallow copying in C++ ====


<source lang="cpp">
<source lang="cpp">
Line 145: Line 145:
</source>
</source>


==== Output ====
===== Output =====
<source lang="cpp">
<source lang="cpp">


Line 160: Line 160:
This performs a ''shallow copy''; if you had an object that contained pointers to other objects, and you wanted to perform a ''deep copy'', you would need to provide a custom copy constructor that also copies the objects pointed to by those pointers.
This performs a ''shallow copy''; if you had an object that contained pointers to other objects, and you wanted to perform a ''deep copy'', you would need to provide a custom copy constructor that also copies the objects pointed to by those pointers.


=== Copying in Java ===
=== In Java ===


Unlike in C++, objects in Java are always accessed indirectly through [[Reference (computer science)|references]]. Objects are never created implicitly but instead are always passed or assigned by reference. The [[Java Virtual Machine|virtual machine]] takes care of [[garbage collection (computer science)|garbage collection]] so that objects are cleaned up after they are no longer reachable. There is no automatic way to copy any given object in Java.
Unlike in C++, objects in Java are always accessed indirectly through [[reference (computer science)|references]]. Objects are never created implicitly but instead are always passed or assigned by reference. The [[Java Virtual Machine]] manages [[garbage collection (computer science)|garbage collection]] so that objects are cleaned up after they are no longer reachable. There is no automatic way to copy any given object in Java.


Copying is usually performed by a [[clone (Java method)|clone() method]] of a class. This method usually, in turn, calls the clone() method of its parent class to obtain a copy, and then does any custom copying procedures. Eventually this gets to the clone() method of <code>Object</code> (the uppermost class), which creates a new instance of the same class as the object and copies all the fields to the new instance (a "shallow copy"). If this method is used, the class must implement the {{Javadoc:SE|java/lang|Cloneable}} marker interface, or else it will [[Exception handling|throw]] a CloneNotSupportedException. After obtaining a copy from the parent class, a class's own clone() method may then provide custom cloning capability, like deep copying (i.e. duplicate some of the structures referred to by the object) or giving the new instance a new unique ID.
Copying is usually performed by a [[clone (Java method)|clone() method]] of a class. This method usually, in turn, calls the clone() method of its parent class to obtain a copy, and then does any custom copying procedures. Eventually this gets to the clone() method of <code>Object</code> (the uppermost class), which creates a new instance of the same class as the object and copies all the fields to the new instance (a "shallow copy"). If this method is used, the class must implement the {{Javadoc:SE|java/lang|Cloneable}} marker interface, or else it will [[exception handling|throw]] a CloneNotSupportedException. After obtaining a copy from the parent class, a class's own clone() method may then provide custom cloning capability, like deep copying (i.e. duplicate some of the structures referred to by the object) or giving the new instance a new unique ID.


One disadvantage is that the return type of clone() is <code>Object</code>, and needs to be explicitly [[Type conversion|cast back]] into the appropriate type (technically a custom clone() method could return another type of object; but that is generally inadvisable). One advantage of using clone() is that since it is an [[Method overriding (programming)|overridable method]], we can call clone() on any object, and it will use the clone() method of its actual class, without the calling code needing to know what that class is (which would be necessary with a copy constructor).
One disadvantage is that the return type of clone() is <code>Object</code>, and needs to be explicitly [[type conversion|cast back]] into the appropriate type (technically a custom clone() method could return another type of object; but that is generally inadvisable). One advantage of using clone() is that since it is an [[method overriding (programming)|overridable method]], we can call clone() on any object, and it will use the clone() method of its actual class, without the calling code needing to know what that class is (which would be necessary with a copy constructor).


Another disadvantage is that one often cannot access the clone() method on an abstract type. Most interfaces and abstract classes in Java do not specify a public clone() method. As a result, often the only way to use the clone() method is if the actual class of an object is known, which is contrary to the abstraction principle of using the most generic type possible. For example, if one has a List reference in Java, one cannot invoke clone() on that reference because List specifies no public clone() method. Actual implementations of List like ArrayList and LinkedList all generally have clone() methods themselves, but it is inconvenient and bad abstraction to carry around the actual class type of an object.
Another disadvantage is that one often cannot access the clone() method on an abstract type. Most interfaces and abstract classes in Java do not specify a public clone() method. As a result, often the only way to use the clone() method is if the actual class of an object is known, which is contrary to the abstraction principle of using the most generic type possible. For example, if one has a List reference in Java, one cannot invoke clone() on that reference because List specifies no public clone() method. Actual implementations of List like ArrayList and LinkedList all generally have clone() methods themselves, but it is inconvenient and bad abstraction to carry around the actual class type of an object.


Another way to copy objects in Java is to [[serialization|serialize]] them through the {{Javadoc:SE|java/io|Serializable}} interface. This is typically used for [[Persistence (computer science)|persistence]] and [[wire protocol]] purposes, but it does create copies of objects and, unlike clone, a deep copy that gracefully handles cycled graphs of objects is readily available with minimal effort from the programmer.
Another way to copy objects in Java is to [[serialization|serialize]] them through the {{Javadoc:SE|java/io|Serializable}} interface. This is typically used for [[persistence (computer science)|persistence]] and [[wire protocol]] purposes, but it does create copies of objects and, unlike clone, a deep copy that gracefully handles cycled graphs of objects is readily available with minimal effort from the programmer.


Both of these methods suffer from a notable problem: the [[Constructor (computer science)|constructor]] is not used for objects copied with clone or serialization. This can lead to bugs with improperly initialized data, prevents the use of [[Final (Java)|<code>final</code>]] member fields, and makes maintenance challenging. Some utilities attempt to overcome these issues by using reflection to deep copy objects, such as [http://www.genericdeepcopy.com/ Generic Deep Copy] and the [http://robust-it.co.uk/clone/ Java Deep-Cloning library].
Both of these methods suffer from a notable problem: the [[constructor (computer science)|constructor]] is not used for objects copied with clone or serialization. This can lead to bugs with improperly initialized data, prevents the use of [[final (Java)|<code>final</code>]] member fields, and makes maintenance challenging. Some utilities attempt to overcome these issues by using reflection to deep copy objects, such as generic deep copy<ref>[http://www.genericdeepcopy.com/ Java generic deep copy]</ref> and the deep-cloning library.<ref>[http://robust-it.co.uk/clone/ Java deep-cloning library]</ref>


=== Copying in Eiffel ===
=== In Eiffel ===


Runtime objects in [[Eiffel (programming language)|Eiffel]] are accessible either indirectly through [[Reference (computer science)|references]] or as ''expanded'' objects whose fields are embedded within the objects that use them. That is, fields of an object are stored either [[Reference (computer science)#External and internal storage|externally or internally]].
Runtime objects in [[Eiffel (programming language)|Eiffel]] are accessible either indirectly through [[reference (computer science)|references]] or as ''expanded'' objects whose fields are embedded within the objects that use them. That is, fields of an object are stored either [[reference (computer science)#External and internal storage|externally or internally]].


The Eiffel class <code lang="eiffel">ANY</code> contains features for shallow and deep copying and cloning of objects. All Eiffel classes inherit from <code lang="eiffel">ANY</code>, so these features are available within all classes, and are applicable both to reference and expanded objects.
The Eiffel class <code lang="eiffel">ANY</code> contains features for shallow and deep copying and cloning of objects. All Eiffel classes inherit from <code lang="eiffel">ANY</code>, so these features are available within all classes, and are applicable both to reference and expanded objects.
Line 207: Line 207:
The anchored type declares that the type of the result of <code lang="eiffel">twin</code> will be the same as the type of the target of the call ( <code lang="eiffel">Current</code> ).
The anchored type declares that the type of the result of <code lang="eiffel">twin</code> will be the same as the type of the target of the call ( <code lang="eiffel">Current</code> ).


Deep copying and the creation of deep twins can be done by using the features <code lang="eiffel">deep_copy</code> and <code lang="eiffel">deep_twin</code>, again inherited from class <code lang="eiffel">ANY</code>. These features have the potential to create many new objects, because they duplicate all the objects in an entire object structure. Because new duplicate objects are created instead of simply copying references to existing objects, deep operations will become a source of performance issues more readily than shallow operations.
Deep copying and creating deep twins can be done using the features <code lang="eiffel">deep_copy</code> and <code lang="eiffel">deep_twin</code>, again inherited from class <code lang="eiffel">ANY</code>. These features have the potential to create many new objects, because they duplicate all the objects in an entire object structure. Because new duplicate objects are created instead of simply copying references to existing objects, deep operations will become a source of performance issues more readily than shallow operations.


=== Copying in other languages ===
=== In other languages ===
In [[Objective-C]], the methods <code>copy</code> and <code>mutableCopy</code> are inherited by all objects and intended for performing copies; the latter is for creating a mutable type of the original object. These methods in turn call the <code>copyWithZone</code> and <code>mutableCopyWithZone</code> methods, respectively, to perform the copying. An object must implement the corresponding <code>copyWithZone</code> method to be copyable. To perform the copying, the copying function may call the <code>NSCopyObject()</code> function on the object to get a byte-for-byte shallow copy.
The [[Python (programming language)|Python]] library's [http://www.python.org/doc/2.5.2/lib/module-copy.html copy] module provides shallow copy and deep copy of objects through the <code>copy()</code> and <code>deepcopy()</code> functions, respectively. Programmers may define special methods <code>__copy__()</code> and <code>__deepcopy__()</code> in an object to provide custom copying implementation.


In [[Objective Caml]], the [[library (computing)|library]] function [http://caml.inria.fr/pub/docs/manual-ocaml/libref/Oo.html#VALcopy Oo.copy] performs shallow copying of an object.
In [[PHP (programming language)|PHP]], the <code>clone</code> keyword performs shallow copying of an object.[http://www.php.net/manual/en/language.oop5.cloning.php] Programmers may define a special method <code>__clone()</code> in an object to provide custom copying implementation.


In [[PHP]], the <code>clone</code> keyword performs shallow copying of an object.[http://www.php.net/manual/en/language.oop5.cloning.php] Programmers may define a special method <code>__clone()</code> in an object to provide custom copying implementation.
In [[Ruby (programming language)|Ruby]], all objects inherit two methods for performing shallow copies, [http://www.ruby-doc.org/docs/ProgrammingRuby/html/ref_c_object.html#Object.clone clone] and [http://www.ruby-doc.org/docs/ProgrammingRuby/html/ref_c_object.html#Object.dup dup]. The two methods differ in that <code>clone</code> copies an object's tainted state, frozen state, and any [[Singleton pattern|Singleton]] methods it may have, whereas <code>dup</code> copies only its tainted state. Deep copies may be achieved by dumping and loading an object's byte stream or YAML serialization.[http://www.ruby-doc.org/docs/ProgrammingRuby/html/classes.html#S5]


In [[Python (programming language)|Python]], the library's [http://www.python.org/doc/2.5.2/lib/module-copy.html copy] module provides shallow copy and deep copy of objects through the <code>copy()</code> and <code>deepcopy()</code> functions, respectively. Programmers may define special methods <code>__copy__()</code> and <code>__deepcopy__()</code> in an object to provide custom copying implementation.
In [[OCaml]], the library function [http://caml.inria.fr/pub/docs/manual-ocaml/libref/Oo.html#VALcopy Oo.copy] performs shallow copying of an object.


In [[Ruby (programming language)|Ruby]], all objects inherit two methods for performing shallow copies, [http://www.ruby-doc.org/docs/ProgrammingRuby/html/ref_c_object.html#Object.clone clone] and [http://www.ruby-doc.org/docs/ProgrammingRuby/html/ref_c_object.html#Object.dup dup]. The two methods differ in that <code>clone</code> copies an object's tainted state, frozen state, and any [[singleton pattern|singleton]] methods it may have, whereas <code>dup</code> copies only its tainted state. Deep copies may be achieved by dumping and loading an object's byte stream or YAML serialization.[http://www.ruby-doc.org/docs/ProgrammingRuby/html/classes.html#S5]
In [[Objective-C]], the methods <code>copy</code> and <code>mutableCopy</code> are inherited by all objects and intended for performing copies; the latter is for creating a mutable type of the original object. These methods in turn call the <code>copyWithZone</code> and <code>mutableCopyWithZone</code> methods, respectively, to perform the copying. An object must implement the corresponding <code>copyWithZone</code> method in order for it to be copyable. To perform the actual copying, the copying function may call the <code>NSCopyObject()</code> function on the object to get a byte-for-byte shallow copy.


== See also ==
== See also ==
Line 225: Line 225:
* [[Reference counting]]
* [[Reference counting]]
* [[Copy-on-write]]
* [[Copy-on-write]]
* [[clone (Java method)]]
* [[Clone (Java method)]]

== References ==
{{reflist}}


{{DEFAULTSORT:Object Copy}}
{{DEFAULTSORT:Object Copy}}

Revision as of 21:00, 25 November 2010

One of the most common procedures that occurs in computer programs is the copying of data. An object is a composite data type in object-oriented programming languages. Object copy thus describes the action wherein an object has its attributes copied to another object of the same data type. An object may be copied to reuse all or part of its data in a new context.

Deep vs. Shallow vs. Lazy copy

The design goal of most objects is to give the semblance of being made out of one monolithic block even though most are not. As objects are made up of several different parts, copying becomes non trivial. Several strategies exist to attack this problem.

Consider two objects, A and B, which each refer to two memory blocks xi and yi (i = 1, 2,...). Think of A and B as strings and of xi and yi (i = 1, 2,...) as the characters they contain.

The following paragraphs explain different strategies for copying A into B.

Shallow copy

One of them is the shallow copy. In this process B is attached to the same memory block as A.This is otherwise known as address copy.

This results in a situation in which some data is shared between A and B, thus modifying the one will alter the other. The original memory block of B is now no longer referred to from anywhere. If the language does not have automatic garbage collection the original memory block of B has probably been leaked.

The advantage of shallow copies is that their execution speed is fast and does not depend on the size of the data.

Bitwise copies of objects which are not made up of a monolithic block are shallow copies.

Deep copy

An alternative is a deep copy. Here the data are actually copied over.

The result is different from the result a shallow copy gives. The advantage is that A and B do not depend on each other but at the cost of a slower more expensive copy.

Lazy copy

A lazy copy is a combination of both strategies above. When initially copying an object, a (fast) shallow copy is used. A counter is also used to track how many objects share the data. When the program wants to modify an object, it can determine if the data is shared (by examining the counter) and can do a deep copy if necessary.

Lazy copy looks to the outside just as a deep copy but takes advantage of the speed of a shallow copy whenever possible. The downside are rather high but constant base costs because of the counter. Also, in certain situations, circular references can also cause problems.

Lazy copy is related to copy-on-write.

How to copy objects

Nearly all object-oriented programming languages provide some way to copy objects. As the majority of languages do not provide most objects themselves, the programmer has to define how an object should be copied, just as he or she has to define if two objects are identical or even comparable in the first place. Many languages provide some default behavior.

How copying is solved varies from language to language and what concept of an object it has. The following presents examples for two of the most widely used object-oriented languages, C++ and Java, which should cover nearly every way that an object-oriented language can attack this problem.

In C++

C++ is designed so that user-defined types should be able to function exactly like native types such as char and int. One way in which C++ achieves this is by allowing any class to define a copy constructor and an assignment operator. C++ provides default versions of these which perform a memberwise copy, but any class is free to disable copying or define its own copy behaviour.

class Vector
{
public:
    Vector() { x = 0; y = 0; } // Standard constructor

    Vector(const Vector& other) // Copy constructor 
    {
        x = other.x;
        y = other.y;
    }
 
    Vector& operator=(const Vector& other) // Assignment operator 
    {
        x = other.x;
        y = other.y;

        return *this;
    }

    // [Other member functions needed to make class useful]

private:
    int x, y;
};

void foo(Vector v)
{
    // [Some code here]
}

void bar()
{
    Vector v1; // v1 will be constructed by the standard constructor
    
    foo(v1); // The copy constructor will be used to create a copy of v1

    Vector v2 = v1; // v2 will typically be constructed by the copy constructor

    Vector v3;
    v3 = v1; // The assignment operator will be used here
}

Another example of deep and shallow copying in C++

//DEEP and SHALLOW copy concept example, for classes with primitive members
//(for classes with dynamic member data, a copy constructor would be needed for a deep copy):
#include <iostream>

class base
{
public:
	int i;

	base()
	{
		i=0;
	}

	base(int j)
	{
		i=j;
	}
};

int main()
{
	using namespace std;

	base *p1=new base(23);
	base *p2;
//Shallow copy 
	p2=p1;                                                  // address is copied 
	cout<<"\naddress of P1:"<<p1;
	cout<<"\nvalue at p1:"<<p1->i;
	cout<<"\naddress of P2:"<<p2;
	cout<<"\nvalue at p2:"<<p2->i;
	delete p2;
	cout<<"\naddress of P1 after delete:"<<p1;
	cout<<"\nvalue in P2 after delete:"<<p2->i;           // behaviour undefined, will cause a run-time fault on many systems

//DEEP copy	
	base o1(67);
	base o2;
	o2=o1;                                                //contents are copied. But, the addresses remained different
	cout<<"\nvalue in o1:"<<o1.i;
	cout<<"\nvalue in o2 after copy:"<<o2.i<<endl;
	return 0;
}
Output
address of P1:0x00323C88
value at p1:23
address of P2:0x00323C88
value at p2:23
address of P1 after delete:0x00323C88
value in P2 after delete:-572662307
value in o1:67
value in o2 after copy:67

This performs a shallow copy; if you had an object that contained pointers to other objects, and you wanted to perform a deep copy, you would need to provide a custom copy constructor that also copies the objects pointed to by those pointers.

In Java

Unlike in C++, objects in Java are always accessed indirectly through references. Objects are never created implicitly but instead are always passed or assigned by reference. The Java Virtual Machine manages garbage collection so that objects are cleaned up after they are no longer reachable. There is no automatic way to copy any given object in Java.

Copying is usually performed by a clone() method of a class. This method usually, in turn, calls the clone() method of its parent class to obtain a copy, and then does any custom copying procedures. Eventually this gets to the clone() method of Object (the uppermost class), which creates a new instance of the same class as the object and copies all the fields to the new instance (a "shallow copy"). If this method is used, the class must implement the Cloneable marker interface, or else it will throw a CloneNotSupportedException. After obtaining a copy from the parent class, a class's own clone() method may then provide custom cloning capability, like deep copying (i.e. duplicate some of the structures referred to by the object) or giving the new instance a new unique ID.

One disadvantage is that the return type of clone() is Object, and needs to be explicitly cast back into the appropriate type (technically a custom clone() method could return another type of object; but that is generally inadvisable). One advantage of using clone() is that since it is an overridable method, we can call clone() on any object, and it will use the clone() method of its actual class, without the calling code needing to know what that class is (which would be necessary with a copy constructor).

Another disadvantage is that one often cannot access the clone() method on an abstract type. Most interfaces and abstract classes in Java do not specify a public clone() method. As a result, often the only way to use the clone() method is if the actual class of an object is known, which is contrary to the abstraction principle of using the most generic type possible. For example, if one has a List reference in Java, one cannot invoke clone() on that reference because List specifies no public clone() method. Actual implementations of List like ArrayList and LinkedList all generally have clone() methods themselves, but it is inconvenient and bad abstraction to carry around the actual class type of an object.

Another way to copy objects in Java is to serialize them through the Serializable interface. This is typically used for persistence and wire protocol purposes, but it does create copies of objects and, unlike clone, a deep copy that gracefully handles cycled graphs of objects is readily available with minimal effort from the programmer.

Both of these methods suffer from a notable problem: the constructor is not used for objects copied with clone or serialization. This can lead to bugs with improperly initialized data, prevents the use of final member fields, and makes maintenance challenging. Some utilities attempt to overcome these issues by using reflection to deep copy objects, such as generic deep copy[1] and the deep-cloning library.[2]

In Eiffel

Runtime objects in Eiffel are accessible either indirectly through references or as expanded objects whose fields are embedded within the objects that use them. That is, fields of an object are stored either externally or internally.

The Eiffel class ANY contains features for shallow and deep copying and cloning of objects. All Eiffel classes inherit from ANY, so these features are available within all classes, and are applicable both to reference and expanded objects.

The copy feature is shown below being applied to x with an argument y.

            x.copy (y)

This effects a shallow, field-by-field copy from the object associated with y to the object associated with x.

In this case no new object is created. The same objects referenced by y before the application of copy, will also be referenced by x after the copy feature completes, as in the explanation of shallow copy above.

To effect the creation of a new object which is a shallow duplicate of y, the feature twin is used. Below, a new object identical to y is created and assigned to x.

            x :=  y.twin

The single new object is created with its fields identical to those of y.

The feature twin relies on the feature copy, which can be redefined in descendants of ANY, if necessary. The result of twin is of the anchored type like Current, as shown in the contract for twin below, excerpted from class ANY.

    frozen twin: like Current
            -- New object equal to `Current'
            -- twin calls copy; to change copying/twining semantics, redefine copy.
        ensure
            twin_not_void: Result /= Void
            is_equal: Result ~ Current

The anchored type declares that the type of the result of twin will be the same as the type of the target of the call ( Current ).

Deep copying and creating deep twins can be done using the features deep_copy and deep_twin, again inherited from class ANY. These features have the potential to create many new objects, because they duplicate all the objects in an entire object structure. Because new duplicate objects are created instead of simply copying references to existing objects, deep operations will become a source of performance issues more readily than shallow operations.

In other languages

In Objective-C, the methods copy and mutableCopy are inherited by all objects and intended for performing copies; the latter is for creating a mutable type of the original object. These methods in turn call the copyWithZone and mutableCopyWithZone methods, respectively, to perform the copying. An object must implement the corresponding copyWithZone method to be copyable. To perform the copying, the copying function may call the NSCopyObject() function on the object to get a byte-for-byte shallow copy.

In Objective Caml, the library function Oo.copy performs shallow copying of an object.

In PHP, the clone keyword performs shallow copying of an object.[1] Programmers may define a special method __clone() in an object to provide custom copying implementation.

In Python, the library's copy module provides shallow copy and deep copy of objects through the copy() and deepcopy() functions, respectively. Programmers may define special methods __copy__() and __deepcopy__() in an object to provide custom copying implementation.

In Ruby, all objects inherit two methods for performing shallow copies, clone and dup. The two methods differ in that clone copies an object's tainted state, frozen state, and any singleton methods it may have, whereas dup copies only its tainted state. Deep copies may be achieved by dumping and loading an object's byte stream or YAML serialization.[2]

See also

References