objective-cpointerspropertiesprotocolsnscopying

data type not checked when copy method is used in assignment


I have a doubt regarding copy

Overview:

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);
}

Solution

  • -[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.