2011-12-14 51 views
16

如果您有类似下面@synthesized实例变量的可见性是什么?

@interface MyClass : NSObject 
@property(strong) NSString *myProp; 
@end 

你的公共接口属性,然后合成它,实际上合成变量:

@implementation MyClass 
@synthesize myProp = _myProp; // or just leave it at the default name.. 
@end 

什么是实例变量_myProp知名度?也就是说,这是否被认为是@public,@protected@private?我猜是因为MySubClass可以从MyClass继承,那么它也会获得属性(自然),但它是否也会继承实例变量的可见性?

如果我将该属性放入类扩展中,它会产生什么区别?这会隐藏子类的属性,我也在猜测实例变量。这是记录在任何地方?

回答

28

一个合成的伊娃是完全看不见所有的代码,看不到@synthesize行(基本上意味着.m文件之外的任何东西)。这不是@protected,它不是@private,它只是未知数。使用一个@private伊娃,其他代码试图访问它将被告知它是私人的,但是对于一个合成的伊娃,其他代码试图访问它将被告知该字段根本不存在。

作为一个思想实验,尝试想象一下,伊娃采取的行为就像是@protected。你创建了一个子类,然后你在那里与伊娃混在一起。现在你回到超类,并将@synthesize myProp更改为@synthesize myProp=foo。子类会发生什么?当编译器处理子类时,它看不到@synthesize行,所以它不知道你只是改变了伊娃的名字。事实上,它甚至无法说明该财产是否完全由伊娃支持,或者是否通过自定义编写的访问方法实施。我希望这很明显,这意味着为什么这意味着子类不可能访问伊娃,而其他任何一类都不可能。

这就是说,我不太清楚编译器如果在试图访问伊娃的相同.m文件中编写代码。我期望它会将伊娃视为@private(因为编译器实际上可以看到伊娃存在)。

此外,这些对运行时方法没有任何影响。其他类仍然可以使用obj-c运行时方法来动态查找您的类的ivar列表,​​并仔细查看它。

+6

很好解释! – 2011-12-14 20:19:12

1

如果它是在您的界面中声明的,它在使用@property声明时几乎是公开的。如果你想使用@property声明,并保持它们的属性真正私有,你应该在你的实现中创建一个私有类。

MyClass.h

@interface MyClass : NSObject { 
@private 
    NSObject* foo; 
} 
@end 

MyClass.m

#import "ClassWithPrivateProperty.h" 

@interface MyClass() 
    @property (nonatomic,retain) NSObject* foo; 
@end 

@implementation MyClass 
@synthesize foo; 
// class implementation... 
@end 
+1

很好的建议,但没有提到伊娃自身的知名度。 – 2011-12-14 20:13:11

+1

你的回答并没有真正解决支持ivar _itself_的可见性。 – 2011-12-14 20:18:10

1

一个合成的变量就如同宣布@private

@interface Garble : NSObject 
@property (copy) NSString * s; 
@end 
@implementation Garble 
@synthesize s; 
@end 

@interface Bargle : Garble 
@end 

@implementation Bargle 

- (void) useS { 
    NSLog(@"%@", s); // error: instance variable 's' is private 
} 

@end 

我发誓我见过这在the docs,但我现在找不到它。如果我追踪它,将会更新。

0

其他类可以访问它们的所有内容#include。换句话说,就是你的标题中的所有内容。

如果某些内容仅出现在您的实现文件中,其他类(包括子类)不知道它存在。综合性质就是这样。其他类只知道属性(属性意味着一个getter和一个setter方法),但他们不知道其方法的内部实现。

请注意,obj-c中的访问说明符(public/private/protected)仅是编译器的一个提示,即使头文件中出现某些内容,也无法访问它。运行时不会以任何方式检查它。

如果将其放入类扩展中会发生什么?请注意,属性是一组两种方法。您只需隐藏每个包含您的类主标题但不包含类扩展标题的类的方法。

我们使用这个例子来声明一个属性为只读属性,并在类继续中声明它为readwrite。然后,我们只能从课堂内部使用setter。

1

您可以创建一个动态属性,并向编译器指出它的实例化将在运行时。

然后在你的子类中编写自己的getter或综合属性。

@interface BaseClass的:NSObject的

@属性(非原子,强)的NSString * ThisWillBeSynthesizedInRespectiveSubclasses;

@end

@implementation BaseClass的

@dynamic ThisWillBeSynthesizedInRespectiveSubclasses;

@end

在子类

@interface亚纲:BaseClass的

@end

@implementation子类 @synthesize ThisWillBeSynthesizedInRespectiveSubclasses = _ThisWillBeSynthesizedInRespectiveSubclasses;

@end

或者您编写自己的setter/getter方法。

希望这会有所帮助!