0

I have a doubt regarding copy

Overview:

  • I have 2 classes namely Car and MutableCar
  • Both these classes conform to the protocol NSCopying
  • The method copy would return an instance of Car

Question

  1. Why doesn't the compiler doesn't throw any compilation error for the following statement?

    MutableCar* c2 = [c1 copy];

    The compiler allows me to assign Car* to a MutableCar* pointer variable

  2. Is there any way that this can be prevented from going unnoticed at compile time?

    IMHO this could lead to crashes at runtime as shown in the example below.

Code (in separate files)

Points to note - Automatic Reference Counting (ARC) is used

Car.h

#import<Foundation/Foundation.h>

@interface Car : NSObject <NSCopying>
@property (readonly) int n1;
@end

Car.m

#import"Car.h"
#import"MutableCar.h"

@interface Car()                //extension
@property (readwrite) int n1;
@end

@implementation Car

@synthesize n1 = _n1;

- (id) copyWithZone: (NSZone*) pZone
{
    Car* newInstance = [[Car alloc] init];
    newInstance -> _n1 = _n1;
    return(newInstance);
}
@end

MutableCar.h

#import"Car.h"

@interface MutableCar : Car 
@property int n1;            // redeclaration
@property int n2;

@end

MutableCar.m

#import"MutableCar.h"

@implementation MutableCar
@dynamic n1;
@synthesize n2 = _n2;
@end

test.m

#import"MutableCar.h"

int main()
{
    MutableCar* c1 = [[MutableCar alloc] init];
    MutableCar* c2 = [c1 copy];                     //Car* is being assigned to MutableCar* variable
                                                    //Why doesn't the compiler doesn't throw any compilation error ?


    //c2.n2 = 20;                                     //At runtime this throws an error, because c2 is not a MutableCar instance 

    return(0);
}
Jason Aller
  • 3,541
  • 28
  • 38
  • 38
user1046037
  • 16,755
  • 12
  • 92
  • 138

1 Answers1

1

-[NSObject copy] is declared to return id, a type is assignable to any object pointer. That's why you don't get an error or a warning.

If you override copy in @interface Car, declaring it to return Car *, you'll get a compiler warning on your bogus assignment.

rob mayoff
  • 375,296
  • 67
  • 796
  • 848
  • thanks for the reply Rob, but I tried overriding the `NSCopying` protocol earlier and yet it didn't throw an error at compile time. Just to double confirm below mentioned is my redeclaration in the interface of Car: `- (Car*) copyWithZone: (NSZone*) pZone;` – user1046037 Dec 09 '11 at 05:14
  • You're not sending the `copyWithZone:` message in your main function. You're sending `copy`. The compiler doesn't care about what's in some library somewhere. It cares about what's in the source code you feed it. – rob mayoff Dec 09 '11 at 05:23
  • Thanks a lot, it works great! you are correct NSObject's copy returns id which needs to be overridden. – user1046037 Dec 09 '11 at 06:04