Автоматический синтез свойств (@property) и наследование

В XCode 5.1 появляется новое предупреждение. Это заставило меня понять очевидно, что я делаю что-то не так.

Идея заключалась в том, чтобы иметь объект (модель) и его изменяемую версию, которая наследуется от исходного класса. Итак, идея состоит в том, чтобы открыть собственность, которая была с readonly по readwrite.

@interface Car : NSObject
    @property (strong, readonly) NSString *name;
@end

@interface MutableCar : Car
    @property (strong, readwrite) NSString *name;
@end

Они должны быть в отдельных файлах (например, два обычных класса).

И это дает это предупреждение:

Auto property synthesis will not synthesize property 'name' because it is 'readwrite' but it will be synthesized 'readonly' via another property

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


person Tancrede Chazallet    schedule 13.03.2014    source источник
comment
Я не могу воспроизвести предупреждения с данным кодом.   -  person Tim    schedule 13.03.2014
comment
Я сделал, и да, вам нужно поместить его в отдельный файл, чтобы он был (создайте оба класса)   -  person Tancrede Chazallet    schedule 13.03.2014
comment
Любой флаг, который я мог бы передать или игнорировать, чтобы избавиться от этого?   -  person gran_profaci    schedule 17.08.2017


Ответы (1)


Я бы предложил явно синтезировать свойство в вашей реализации MutableCar. Как в:

@implementation MutableCar

@synthesize name;

@end

Таким образом, clang не будет пытаться использовать автосинтез.

Редактировать:

Если вы не хотите использовать инкапсуляцию и по другой причине вам нужно получить доступ к ivar из родительского класса, вам нужно приложить немного больше усилий:

Сначала файл Car .h остается прежним (я добавил метод printVar для печати ivar и свойства):

@interface Car : NSObject

- (void)printVar;

@property (strong, readonly) NSString *name;

@end

Теперь в файле .m я реализую метод printVar, а также добавляю расширение класса, чтобы указать clang создать установщик:

// Private class extension, causes setName: to be created but not exposed.
@interface Car ()

@property (strong, readwrite) NSString *name;

@end

@implementation Car

- (void)printVar
{
    NSLog(@"<Car> Hello %@, ivar: %@", self.name, _name);
}

@end

Теперь вы можете создать свой MutableCar.h, как и раньше:

@interface MutableCar : Car

@property (strong, readwrite) NSString *name;

@end

и ваш MutableCar.m должен выглядеть так:

@implementation MutableCar

@dynamic name;

- (void)printVar
{
    [super printVar];
    NSLog(@"<MutableCar> Hello %@", self.name);
}

@end

Таким образом, _name ivar для родителя фактически записывается с использованием родительского сеттера, и вы можете получить к нему доступ.

person fz.    schedule 13.03.2014
comment
Означает ли это какую-либо разницу в функциональности или это будет то же самое? - person Tancrede Chazallet; 14.03.2014
comment
После его использования это не очень хороший ответ, он точный и удаляет предупреждение, но он меняет способ его работы, поскольку создает новый iVar в дочернем классе, а не использует родительский, как он защищен. - person Tancrede Chazallet; 14.03.2014
comment
@anc Можете ли вы показать мне ваш точный случай? У вас есть конкретный ivar для этого свойства?. Этот случай должен работать, см. этот пример: gist.github.com/Reflejo/11c91b929bf021308b95 - person fz.; 14.03.2014
comment
@ancAinu Вы получите: Car1: имя для тестирования и Car2: имя для тестирования. Вам нужен явный доступ к ivar на MutableCar? - person fz.; 14.03.2014