Objective-C私有方法困境

10

我知道Objective-C并不支持真正的私有方法。目前我为了声明“私有”方法,将以下内容添加到类.m文件中:

@interface MyClass() 

- (void) privateMethodName;

@end

问题:

如果我现在添加一个子类,并想使用这个“私有”方法,我不能!我会得到以下错误信息:

实例消息的接收方类型'SubClassName'没有声明具有选择器'privateMethodName'的方法


那么,如果我不希望非子类能够访问此方法,但希望子类能够访问该方法,我该怎么办?如何最好/正确地实现我的目标?


2
简单的解决方案是不要将它们设为私有。还有其他人会使用你的代码吗?你认为你真的需要那种程度的控制吗? - pe8ter
3
我支持Jordan的观点:并不是每一种方法都应该放在类的公共头文件中。这只会增加噪音,并且大多数情况下,你真的不希望任何外部人员干扰你的内部帮助程序。 - danyowdee
2
@pe8ter 即使你是独自工作,这种程度的控制肯定会有所帮助。认为你已经(准确地)记住了成千上万行代码是愚蠢的。 - justin
2
@pe8ter 如果可能的话,我宁愿以清晰的方式来做事情 :) 如果其他人要修改我的代码,使用子类之外的方法会导致混乱和复杂的代码。 - Jordan Smith
3个回答

16

你可以将"protected"接口与公共接口分开。在主头文件中,只声明公共方法:

MyMagicThingy.h

@interface MyMagicThingy: NSObject

- (void) publicMethod;

@end 

接下来,再添加一个包含受保护方法的额外头文件:

MyMagicThingy+Protected.h:

#import "MyMagicThingy.h"

@interface MyMagicThingy (Protected)

- (void) protectedMethods;

@end

在Objective-C中,你无法拥有“真正”的私有/受保护/公共方法(即:编译器将强制执行访问规则。所有方法都是公共的)。你必须使用一种约定。


+1 这可能是在严格的 ObjC 上下文中解决问题的最佳通用方法。这个答案和我之前给出的一样,带有一个好的例子。 - justin
啊,我以前见过受保护的接口,但从未意识到它们实际上是做什么的。谢谢! - Jordan Smith

2
你所描述的是一个受保护的方法。一种克服这个问题的方法是:可以声明实例为@public、@protected或@private。你可以声明一个受保护的辅助实例来限制对派生实例的访问,然后通过持有它的对象进行回调。
在某些情况下,另一种选择是使子类写入接口,然后将实现保持私有。
有时候,你只需要记录“不要这样做,除非你不是子类”,因为它不是语言的一部分。在这种思维方式下,我最喜欢使用一个单独的头文件来声明受保护方法的类别。它对客户端来说相当隐蔽,但可以通过显式包含向子类公开 -- Dirk 在同一时间提供了一个示例,请查看一下。
最后,如果你熟悉ObjC++,C++提供了这种控制,因此你可以自由地混合模式和可见性。

0

首先

在Objective-C中,你无法阻止任何人调用对象上实现的任何方法(至少不会在剃掉几十把刀片使牦牛不那么防水之前)。

只需不要调用未在公共头文件中声明的方法,这是一种约定(这就是你已经在做的事情)。

其次

上面段落中的“public”一词起到了关键作用:

在Objective-C中(至少在当前版本中),一个类的接口可以使用你在帖子中描述的技术在任意数量的头文件中定义:类扩展。

Apple框架类的一个例子就是具有单独的子类化头文件UIGestureRecognizerSubclass.hUIGestureRecognizer


附言:
你看到的错误让人想起使用ARC,因此你的运行时肯定足够新,甚至可以使用多个实现文件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接