тип данных не проверяется, когда в назначении используется метод копирования - PullRequest
0 голосов
/ 09 декабря 2011

У меня есть сомнения относительно копии

Обзор:

  • У меня есть 2 класса, а именно Car и MutableCar
  • Оба эти класса соответствуют протоколу NSCopying
  • Метод copy вернул бы экземпляр Car

Вопрос

  1. Почему компилятор не выдает ошибку компиляции для следующего оператора?

    MutableCar* c2 = [c1 copy];

    Компилятор позволяет мне назначить Car * дляMutableCar * переменная указателя

  2. Есть ли какой-нибудь способ, которым это может быть предотвращено, чтобы остаться незамеченным во время компиляции?

    ИМХО это может привести к сбоям во время выполнения, как показано в примере ниже.

Код (в отдельных файлах)

Указывает на примечание - используется автоматический подсчет ссылок (ARC)

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

1 Ответ

1 голос
/ 09 декабря 2011

-[NSObject copy] объявлено как возвращающее id, тип может быть назначен любому указателю объекта. Вот почему вы не получаете сообщение об ошибке или предупреждение.

Если вы переопределите copy в @interface Car, заявив, что он возвращает Car *, вы получите предупреждение компилятора о вашем поддельном назначении.

...