公共接口和私有接口/实现文件中声明协议的区别

20

声明这些协议的方式有什么不同?仅仅是在.h文件中声明的协议是公开的吗?

in .h file:
@interface TestViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>

in .m file:
@interface TestViewController () <UISearchBarDelegate, UISearchDisplayDelegate, UIAlertViewDelegate, MKMapViewDelegate, CLLocationManagerDelegate>

1
这是一个很好的问题。我通常会将它们声明为私有的。通常情况下,除非调用者计划将其实例用作委托,否则谁是某个类的委托通常不是别人的事。 - danh
1
同意使用 private 是有道理的,但我大多数情况下看到它们是公开声明的,对我来说不清楚为什么或是否存在某种约定/原因,我还没有理解。 - timpone
4个回答

27
当您将协议添加到.h文件中时,这告诉所有包含该头文件的人该类服从给定的协议。
当您将协议添加到.m文件中时,这基本上是一种私有指示,表示该类遵循协议。只有实现知道。
只有在外部类需要知道该类服从协议时才应使用第一种形式(在.h文件中)。当只有实现关心时,应使用第二种形式(在.m文件中)。
在您给出的示例中,其他类高度不可能需要知道该类服从表视图协议。那些应该在.m文件中。其他类也不太可能需要知道搜索协议。这些是实现细节。这属于.m文件。
可能有情况下您需要同时使用两种形式。这样做没问题。
这是我的指南。除非您有特定需要让其他类知道协议的使用,否则请将其放入.m文件中。

除非您有特定的需求让其他类知道协议的使用,否则请将其放入.m文件中。主要需要覆盖协议的方法吗? - timpone
1
需要覆盖协议方法是一个可能的原因,但不是主要原因。即使协议被添加到.m文件中,您也可以覆盖协议方法。唯一的注意事项是覆盖方法不能调用[super protocolMethod]。如果您需要这样做,则必须将协议添加到.h文件中。 - rmaddy
1
天啊,这个业务有点混乱;需要冲个澡,好好想一想。 - timpone

4
除非我错了,如果您还声明了您的类采用该协议,则无法使用前向声明@protocol Foo;
这意味着在您的类的头文件中,您需要包含/导入另一个带有协议声明的头文件。根据项目的大小和复杂性,这可能会导致头文件“依赖地狱”。
是否存在这种真正的危险必须由实际项目来判断。大多数时候,这可能不是您需要关心的问题,但我只是想提一下这个角度。

3

我承认这不可能是样式问题!!!

为什么要将这些协议隐藏在 .m 文件中,也许你的类将与一些框架一起使用。在那里 .h 是可见的,每个人都可以看到“哦呀,这些是这个类的代理协议”。而不是隐藏的魔法。

因此,它被设计成透明而不是不透明。


1

我认为第一种方式更好,这样使用该类的人就知道该类是否实现了某些协议。这只会是一个优势。

协议用于保证某些方法被实现,这是 Objective-C 中不可能实现的多重继承的替代方案。假设我想将符合某些协议的对象传递给函数或方法,并且我必须确保该类实现了某些协议。在这种情况下,我必须知道该类正在实现哪些协议

它还可以消除一些编译器警告,例如以下函数(或方法):

void foo(id< SomeProtocol> obj) {...}

透明度通常是一个好主意,很少是一个劣势。


所以,在 Objective-C 层面上没有什么技术差异吗?一般来说,我理解透明度的概念,但是有人可能很容易地争辩说,面向对象编程的一部分是“隐藏实现”,这似乎非常是一项实现细节。当然,除非它是在子类化时需要被重写的。一个问题是协议可以有可选方法,这使得透明度的概念有点棘手。我并不是在反驳任何东西 - 我真的不知道,只是想学习。 - timpone
唯一的两个区别是用户可以看到它,并且它可以消除某些编译器警告。至于在运行时的技术部分,它都是相同的,所有这些信息都将丢失。 - Ramy Al Zuhouri

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