(不是)傻的Objective-C继承问题时使用属性 - GCC Bug? [英] (Not So) Silly Objective-C inheritance problem when using property - GCC Bug?

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

问题描述

更新 - 许多人坚持我需要为属性声明iVar。有些人说不是这样,因为我使用Modern Runtime(64位)。我可以确认,我已经成功使用@property没有iVars几个月了。因此,我认为'正确'的答案是一个解释为什么在64位我突然必须明确声明iVar时(当只有)当我要从一个子类访问它。到目前为止,我看到的唯一一个是一个可能的GCC bug(感谢Yuji)。不是那么简单...为了澄清可能的错误是这样的:当继承一个基类时,一个孩子不能访问父的iVar IF,该孩子也恰好在访问iVar之前使用@synthesize实现一个UNRELATED访问器。

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.

这里我设置了一个简单的测试B类继承自测试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 Header:

TestA Header:

#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的错误。
我使用内容

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位模式下省略实例变量。
我的GCC 4.2.1在OS X 10.6.3给了我一个错误:

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;

。否则,EXP_BAD_ACCESS将等待您!

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

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

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