自动属性综合(@property)和继承

43

使用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

因此,我想知道如何像这样做正确的解决方案,如果可能的话。是否需要编写访问器并避免使用自动综合,等等。请准确说明并支持您的答案与文档或其他内容。


我无法使用给定的代码重现警告。 - Tim
我做了,是的,你需要把它放在单独的文件中(创建两个类)。 - Tancrede Chazallet
有没有任何标志可以传递或忽略以摆脱这个问题? - gran_profaci
1个回答

60
我建议在您的MutableCar实现中明确合成该属性。代码如下:

我建议在您的MutableCar实现中明确合成该属性。具体如下:

@implementation MutableCar

@synthesize name;

@end

这样clang就不会尝试使用属性自动合成

编辑:

如果您不想使用封装,并且由于其他原因需要从父类访问实例变量,则需要做更多的努力:

首先,Car.h文件保持不变(我添加了一个printVar方法来打印实例变量和属性):

@interface Car : NSObject

- (void)printVar;

@property (strong, readonly) NSString *name;

@end

现在在.m文件中,我正在实现printVar方法并添加一个类扩展来告诉clang创建setter:

// 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 实例变量实际上是通过父类的 setter 方法来设置的,因此您可以访问它。


这是否意味着有任何功能上的差异,还是它将保持相同? - Tancrede Chazallet
使用它后,虽然可以消除警告并提高准确性,但它会改变工作方式,因为它在子类中创建了一个新的iVar,而不是像protected那样使用父类的iVar。 - Tancrede Chazallet
@anc你能展示给我你的确切情况吗?你对该属性有特定的ivar吗?这种情况应该可以工作,查看此示例:https://gist.github.com/Reflejo/11c91b929bf021308b95 - fz.
@ancAinu 你会得到:"Car1: 测试名称" 和 "Car2: 测试名称"。你需要显式访问 MutableCar 上的 ivar 吗? - fz.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接