如果一个子类引用一个超类伊瓦尔,合成一个不相关的属性失败 [英] If a subclass refers to a superclass ivar, synthesizing an unrelated property fails

查看:133
本文介绍了如果一个子类引用一个超类伊瓦尔,合成一个不相关的属性失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

编辑:我刚刚注意到这个其他堆栈溢出问题提出了相同的问题:为什么没有对应的ivar hide superclass ivars的子类@property?



这是一些有趣的行为,我无法在任何官方或非官方(博客,推特,SO问题等)中找到记录。我已经将它归结为它的本质,并在新的Xcode项目中对此进行了测试,但我无法解释它。



MyBaseClass有一个实例变量:

  @interface MyBaseClass:NSObject {
NSObject * fooInstanceVar;
}
@end

MySubclass扩展了MyBaseClass,并声明了一个完全不相关的属性(也就是说,该属性不打算由实例变量支持):

  #importMyBaseClass.h
@interface MySubclass:MyBaseClass {}
@property(nonatomic,retain)NSObject * barProperty;
@end

如果MySubclass的实现 not 合成该属性但实现了访问器方法,一切正常(没有编译器错误):

  #importMySubclass.h
@implementation MySubclass

- (NSObject *)barProperty {
return [[NSObject alloc] init]; //请不要公然违反内存规则。

$ b $ - (void)setBarProperty:(NSObject *)obj {/ * no-op * /}

- (void)doSomethingWithProperty {
NSArray * array = [NSArray arrayWithObjects:self.barProperty,fooInstanceVar,nil];
NSLog(@%@,array);
}
@end

但是如果我删除属性存取方法并替换他们与该属性的合成声明,我得到一个编译器错误:'fooInstanceVar'未声明(首次在此函数中使用)

  #importMySubclass.h
@implementation MySubclass
@synthesize barProperty;

- (void)doSomethingWithProperty {
NSArray * array = [NSArray arrayWithObjects:self.barProperty,fooInstanceVar,nil];
NSLog(@%@,array);
}
@end

如果删除 synthesize 声明,或者如果我没有在MySubclass.m中引用 fooInstanceVar 实例变量,或者如果我把所有接口和实现定义在一个文件中。这个错误在GCC 4.2和GCC / LLVM构建设置中似乎也会发生。



任何人都可以解释这里发生的事情吗?

解决方案

正如在这个问题中回答:目标c xcode 4.0.2:子类无法访问超类变量未在此范围内声明



从文档:Apple Objective-C编程语言:
http://developer.apple.com/library/ios/#documentation/Cocoa /Conceptual/ObjectiveC/Chapters/ocDefiningClasses.html#//apple_ref/doc/uid/TP30001163-CH12-TPXREF125


实例变量是无障碍的减少声明它的类以及继承它的类。所有没有明确的scope指令的实例变量都有@protected作用域。



但是,公共实例变量可以在任何地方被访问,就好像它是C结构中的字段一样。例如:

Worker * ceo = [[Worker alloc] init];

ceo-> boss = nil;

我使用LLVM GCC 4.2编译错误(对于iOS项目,在设备上):


错误:'fooInstanceVar'未声明(首次在此函数中使用)
和使用GCC 4.2的同一个:
错误:'fooInstanceVar'未声明(在此函数中首次使用)

我可以使用LLVM编译器2.0进行编译,但不会出错。

用于编译LLVM GCC 4.2和GCC 4.2,使用self>:


[NSArray arrayWithObjects:self .barProperty,self-> fooInstanceVar,nil];在doSomethingWithProperty方法中


Edit: I just noticed this other Stack Overflow question asking much the same thing: Why does a subclass @property with no corresponding ivar hide superclass ivars?

This is some interesting behavior that I cannot find documented in anything official or unofficial (blog, tweet, SO question, etc). I have boiled it down to its essence and tested this in a fresh Xcode project, but I can't explain it.

MyBaseClass has an instance variable:

@interface MyBaseClass : NSObject {
    NSObject *fooInstanceVar;
}
@end

MySubclass extends MyBaseClass, and declares a totally unrelated property (that is, the property is not intended to be backed by the instance variable):

#import "MyBaseClass.h"
@interface MySubclass : MyBaseClass { }
@property (nonatomic, retain) NSObject *barProperty;
@end

If the implementation of MySubclass does not synthesize the property but implements the accessor methods, everything is fine (no compiler error):

#import "MySubclass.h"
@implementation MySubclass

- (NSObject*)barProperty {
    return [[NSObject alloc] init]; // pls ignore flagrant violation of memory rules.
}

- (void)setBarProperty:(NSObject *)obj { /* no-op */ }

- (void)doSomethingWithProperty {
    NSArray *array = [NSArray arrayWithObjects:self.barProperty, fooInstanceVar, nil];
    NSLog(@"%@", array);
}
@end

But if I remove the property accessor methods and replace them with a synthesize declaration for the property, I get a compiler error: 'fooInstanceVar' undeclared (first use in this function).

#import "MySubclass.h"
@implementation MySubclass
@synthesize barProperty;

- (void)doSomethingWithProperty {
    NSArray *array = [NSArray arrayWithObjects:self.barProperty, fooInstanceVar, nil];
    NSLog(@"%@", array);
}
@end

This error goes away if I remove either the synthesize declaration, or if I do not refer to the fooInstanceVar instance variable from within MySubclass.m, or if I put all interface and implementation definitions in a single file. This error also seems to happen in both GCC 4.2 and GCC/LLVM build settings.

Can anyone explain what's happening here?

解决方案

As replied in this question : objective c xcode 4.0.2: subclass can't access superclass variables "was not declared in this scope"

From the doc : Apple Objective-C Programming Langage : http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocDefiningClasses.html#//apple_ref/doc/uid/TP30001163-CH12-TPXREF125

The instance variable is accessible within the class that declares it and within classes that inherit it. All instance variables without an explicit scope directive have @protected scope.

However, a public instance variable can be accessed anywhere as if it were a field in a C structure. For example:

Worker *ceo = [[Worker alloc] init];

ceo->boss = nil;

I have the compilation error using LLVM GCC 4.2 (for an iOS project, on device) :

error: 'fooInstanceVar' undeclared (first use in this function) and the same one using GCC 4.2 : error: 'fooInstanceVar' undeclared (first use in this function)

I can compile using LLVM Compiler 2.0 whithout error.

For compiling with LLVM GCC 4.2 and GCC 4.2 with the use of self-> :

[NSArray arrayWithObjects:self.barProperty, self->fooInstanceVar, nil]; in the doSomethingWithProperty method.

这篇关于如果一个子类引用一个超类伊瓦尔,合成一个不相关的属性失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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