Objective-C:如何在课堂外隐藏课堂成员?
Posted
技术标签:
【中文标题】Objective-C:如何在课堂外隐藏课堂成员?【英文标题】:Objective-C : How may I hide a class member from outside the class? 【发布时间】:2010-12-30 14:11:11 【问题描述】:我正在与某事作斗争,但找不到任何令人满意的解决方案。
我有一个带有“myMutableArray”成员的类。
我希望该类自行管理在数组中添加和删除项目,因此我不希望任何其他类能够访问该成员并对其调用 NSMutableArray 方法。
在理想情况下,我希望有一个私有的 getter(能够调用 self.myMutableArray)和这个成员的公共 setter。
你知道我是怎么做到的吗?
换句话说:
我想要其他课程
可以打电话
- [oneInstance setMyMutableArray:thisArray]; // set
- oneInstance.myMutableArray = thisArray; // set using setter
- thisArray = oneInstance.myMutableArray; // get
- [oneInstance addItem:anItem]; // add
无法打电话:
- [oneInstance.myMutableArray add:etc...] // add
我想上课
可以打电话
- self.myMytableArray = [NSMutableArray array]; // set
- thisArray = self.myMytableArray ; // get
谢谢。
【问题讨论】:
请注意,你说的一项应该被允许,[oneInstance setMyMutableArray:thisArray];
,和你说的一项不应该被允许,oneInstance.myMutableArray = thisArray;
是完全一样的。点表示法确实调用了设置器;当你写 oneInstance.myMutableArray
时,你并没有直接访问数组。
【参考方案1】:
你有什么需要公共二传手的理由吗?听起来类本身拥有数组。您最好不要提供对该字段的任何公共属性访问,并创建一个将值复制到您的私有字段中的公共方法。
// public interface, in the .h file
@interface MyClass : // superclass, protocols, etc.
- (void) setSomething:(NSArray *)values;
@end
// private interface, not in the .h
@interface MyClass ()
@property (/* attributes */) NSMutableArray *myMutableArray;
@end
@implementation MyClass
@synthesize myMutableArray = myMutableArray_;
- (void) setSomething:(NSArray *)values
[self.myMutableArray setArray:values];
@end
【讨论】:
谢谢。我正在研究这个解决方案。这样做,我如何为外部调用提供吸气剂,但防止像 [oneInstance.myMutableArray add:etc...] 这样的调用? 您无法阻止任何人向任何对象发送消息。如果您希望它是安全的,请提供一个返回数组的非可变副本的方法。 好主意。与我发现的另一种解决方案一起应用,它应该几乎是完美的。请参阅:***.com/questions/3571539/… 调用者是否可以对something=
使用点符号?
您可以将“something”声明为属性,使用@dynamic 关键字让编译器知道您将自己提供方法,并使用方法将非可变接口呈现给可变数组.【参考方案2】:
Foo.h
@interface Foo : NSObject
@property(readonly, retain) NSArray * myReadonlyArray;
- (void) addItem: (Item *) anItem;
- (BOOL) publiclyDoSomething;
@end
Foo.m
@interface Foo()
@property(readwrite, retain) NSMutableArray * myMutableArray;
- (void) doSomethingInPrivate;
@end
@implementation Foo
@synthesize myMutableArray = myMutableArray_;
- (void) addItem: (Item *) anItem
// assuming myMutableArray_ was already iniitialized
[self.myMutableArray addObject: anItem];
- (NSArray *)myReadonlyArray
return self.myMutableArray;
... rest of methods (including the public/private) implementations ...
@end
一些细节:
Objective-C 有“实例变量”,而不是“成员变量”。
上面定义了一个自动合成的公共 getter 和私有 setter。为了清楚起见,我还添加了一个公共方法和一个私有方法。
Objective-C 中的“公共”和“私有”完全由编译器的可见性定义。 myMutableArray
的 setter 和 doSomethingInPrivate
方法只是私有的,因为它们在 @interface
中的声明无法导入。
self.myMutableArray
和 [self myMutableArray]
做同样的事情; .
语法只是等效方法调用的简写(除了这个问题还有一些边缘案例细节)
@interface
中的@property
纯粹是方法声明的简写(带有一些额外的元数据)。
@interface Foo()
是一个类扩展,而不是一个类别。它的存在正是为了上述目的;使用应限制范围的附加声明性信息扩展类的@interface
。它可以出现在一个头文件中,例如,您只能在库的实现中导入该文件以创建库私有功能。
@dynamic
用于@synthesize
和@property
也不 提供常规方法实现。 否则不需要!
我可能忘记了什么。
【讨论】:
完美。只有两个问题:是否可以将公共吸气剂作为“副本”而将私人吸气剂作为保留?大概吧。为什么你说@interface Foo() 不是一个类别?它看起来像一个......这只是语法还是你所做的这种差异的深处有什么? 这仍然允许外部对象执行[[foo myMutableArray] addObject:baz]
... 将属性声明为NSArray
而不是NSMutableArray
怎么样?
添加了带不可变返回的只读数组检索。l 无需创建实际的 NSArray,因为调用者无法智能区分可变数组和不可变数组。以上是关于Objective-C:如何在课堂外隐藏课堂成员?的主要内容,如果未能解决你的问题,请参考以下文章