(并非如此)使用属性时愚蠢的Objective-C 继承问题-GCC 错误? [英] (Not So) Silly Objective-C inheritance problem when using property - GCC Bug?

查看:19
本文介绍了(并非如此)使用属性时愚蠢的Objective-C 继承问题-GCC 错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

更新 - 许多人坚持认为我需要为该财产申报 iVar.有些人不这么认为,因为我使用的是现代运行时(64 位).我可以确认我已经成功使用了没有 iVars 的 @property 几个月了.因此,我认为正确"的答案是对为什么在 64 位上我突然必须明确声明 iVar 时(并且仅当)我将从子类访问它的解释.到目前为止,我看到的唯一一个可能是 GCC 错误(感谢 Yuji).毕竟不是那么简单......要澄清可能的错误是这样的:当从基类继承时,如果孩子也碰巧在访问 iVar 之前使用 @synthesize 实现了一个 UNRELATED 访问器,则孩子无法访问父类的 iVar.

Update - Many people are insisting I need to declare an iVar for the property. Some are saying not so, as I am using Modern Runtime (64 bit). I can confirm that I have been successfully using @property without iVars for months now. Therefore, I think the 'correct' answer is an explanation as to why on 64bit I suddenly have to explicitly declare the iVar when (and only when) i'm going to access it from a child class. The only one I've seen so far is a possible GCC bug (thanks Yuji). Not so simple after all... To clarify the possible bug is this: When inheriting from a base class, a child can not access the parent's iVar IF that child also happens to implement an UNRELATED accessor using @synthesize BEFORE the iVar is accessed.

我已经为此挠头好几个小时了 - 我很少使用继承.

I've been scratching my head with this for a couple of hours - I haven't used inheritance much.

这里我设置了一个简单的 Test B 类,它继承自 Test A,其中声明了一个 ivar.但是我收到编译错误,该变量未声明.这仅在我添加属性和合成声明时发生 - 没有它们也能正常工作.

Here I have set up a simple Test B class that inherits from Test A, where an ivar is declared. But I get the compilation error that the variable is undeclared. This only happens when I add the property and synthesize declarations - works fine without them.

TestA 标头:

#import <Cocoa/Cocoa.h>
@interface TestA : NSObject {
    NSString *testString;
}
@end

TestA 实现为空:

TestA Implementation is empty:

#import "TestA.h"
@implementation TestA  
@end

TestB 标题:

#import <Cocoa/Cocoa.h>
#import "TestA.h"
@interface TestB : TestA {
}
@property (nonatomic, retain) NSString *testProp;
@end

TestB 实现(错误 - 'testString' 未声明)

TestB Implementation (Error - 'testString' is undeclared)

#import "TestB.h"
@implementation TestB
@synthesize testProp;
- (void)testing{
    NSLog(@"test ivar is %@", testString);
}
@end

推荐答案

我认为这是 GCC 4.2.1 的 bug.我用内容制作了文件 foo.m

I think this is the bug of GCC 4.2.1. I made the file foo.m with the content

#import <Foundation/Foundation.h>
@interface TestA : NSObject {
    NSString *testString;
}
@end

@implementation TestA  
@end

@interface TestB : TestA {
}
@property (retain) NSString *testProp;
@end

@implementation TestB
@synthesize testProp;
- (void)testing{
NSLog(@"test ivar is %@", testString);
}
@end

注意在64位模式下省略实例变量是可以的.我在 OS X 10.6.3 上的 GCC 4.2.1 给了我一个错误:

Note that it's OK in the 64 bit mode to omit the instance variable. My GCC 4.2.1 on OS X 10.6.3 gave me an error:

$ gcc -arch x86_64 -c foo.m
aho.m: In function ‘-[TestB testing]’:
aho.m:19: error: ‘testString’ undeclared (first use in this function)
aho.m:19: error: (Each undeclared identifier is reported only once
aho.m:19: error: for each function it appears in.)

通过更改编译没有问题

NSLog(@"test ivar is %@", testString);

NSLog(@"test ivar is %@", self->testString);

Clang 编译没有任何问题.

Clang compiled it without any problem.

( 在 32 位模式下,我得到了

( In the 32 bit mode, I got

$ gcc -arch i386 -c foo.m
aho.m:17: error: synthesized property ‘testProp’ must either be named 
the same as a compatible ivar or must explicitly name an ivar
aho.m: In function ‘-[TestB testing]’:
aho.m:19: error: ‘testString’ undeclared (first use in this function)
aho.m:19: error: (Each undeclared identifier is reported only once
aho.m:19: error: for each function it appears in.)

这是完全预期的行为,正如 Manjunath 所写.)

which is a perfectly expected behavior, as Manjunath wrote.)

然而我认为访问超类的实例变量通常是一个相当糟糕的主意:当你实现超类的方法时,你不能假设任何关于实例变量的信息,因为它可能会在子类可能采取的最糟糕的方式.您至少需要写下允许或不允许对实例变量进行什么样的操作……请记住,您可能需要维护您的代码多年!我更愿意在方法和属性级别的代码的各个部分之间保持编程契约.

However I think it's generally a rather bad idea to access an instance variable of the superclass: when you implement the methods the superclass, you cannot assume anything about the instance variable because it might be tweaked in a worst manner possible by the subclass. You at least need to write down what kind of operation on the instance variable is permitted or not... Remember you might need to maintain your code for years! I would prefer keeping programming contracts between various parts of the code at the level of methods and properties.

最后你应该改变

@property NSString *testProp;

@property (copy) NSString *testProp;

或者至少是

@property (retain) NSString *testProp;

如果您不在 OS X 上使用 GC.否则 EXP_BAD_ACCESS 将等待您!

if you're not using GC on OS X. Otherwise EXP_BAD_ACCESS will await you!

这篇关于(并非如此)使用属性时愚蠢的Objective-C 继承问题-GCC 错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆