Polymorphic copy: Difference between revisions

m
(→‎{{header|Racket}}: Add method to copy transparent structures)
Line 929:
=={{header|Objective-C}}==
All objects inherit the <code>copy</code> method from <code>NSObject</code>, which performs copying. But they must implement the <code>NSCopying</code> protocol (which involves implementing the <code>copyWithZone:</code> method) to actually specify how to copy. Calling <code>copy</code> on an object that does not implement <code>copyWithZone:</code> will result in an error.
 
Implementing copying could be done with the <code>NSCopyObject()</code> function for a simple byte-for-byte shallow copy of the object fields. However, due to it not respecting memory management of object pointer fields, this function is listed in the docs as "very difficult to use correctly", and "likely to be deprecated after Mac OS X 10.6". See [http://robnapier.net/blog/implementing-nscopying-439 this article] for reasons why it this function is problematic.
 
Generally, to implement copying, if your parent class does not implement <code>NSCopying</code>, you explicitly allocate a new object (using the class object <code>[self class]</code> instead of hard-coding the name of a particular class, in order to be polymorphic), and initialize it with your object's data. If your parent class already implements <code>NSCopying</code>, and you wish to customize the copying of your class's fields, then you should get a copy from your parent object's <code>copyWithZone:</code> method, and then perform custom initialization on the copy.
 
<lang objc>@interface T : NSObject
{ }
- (void)identify;
@end
Line 953 ⟶ 950:
 
@interface S : T
{ }
@end
 
Line 965 ⟶ 961:
int main()
{
@autoreleasepool {
T *original = [[S alloc] init];
 
T *another = [original copy];
T *original = [[S alloc] init];
[another identify]; // logs "I am an S"
T *another = [original copy];
[another identify]; // logs "I am an S"
 
}
[another release]; // like "alloc", the object returned by "copy" is "owned" by the caller, so we are responsible for releasing it
[original release];
return 0;
}</lang>
Anonymous user