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:如何在课堂外隐藏课堂成员?的主要内容,如果未能解决你的问题,请参考以下文章

如何在课堂上设置两个外键? DJANGO ORM

中软实训 0727课堂笔记

冒号课堂阅读笔记OO的继承

PyQt5 在课堂外添加和删除标签

PyQt - 课堂外的标签管理

Gtkmm 从课堂外关闭一个 gui 窗口