I have a doubt regarding copy
Overview:
Car
and MutableCar
NSCopying
copy
would return an instance of Car
Question
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
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);
}
-[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.