Objective-C中协议中的init方法

8
昨天我的同事问我,为什么我们不应该在协议中声明一个init方法(initWith...:(...)),以强制实现类提供这样一个初始化器。我对这个问题感到非常惊讶,在我的理解中,这是无意义的。但我找不到一个明确的理由,只知道在协议中声明一个init方法会导致实现方的灵活性降低。
请问您能否给出一个好的理由,为什么应该或者不应该在协议中声明一个init方法?
谢谢!
2个回答

9
你可以在协议中定义方法,这样你的代码就可以调用其他人实现的方法。你和实现你的协议的开发人员之间的“合约”看起来像这样:
  • 定义协议,
  • 其他人实现了你的协议,
  • 别人创建一个实现你的协议的对象,并将其给你,这样
  • 可以调用协议的方法而不知道它们的实现。
为了调用协议的方法,你需要有一个实现它的对象的实例。定义协议的整个意义是从你的代码中删除有关实现协议的类的任何知识: 如果你知道要获取哪个类,那么你可能会跳过协议,直接编程到类。然而,如果你想调用你的init, 你必须要么知道类,要么其他人必须给你一个没有调用initalloc的对象。两种选择都不好 - 第一种选择破坏了拥有协议的目的,第二种选择强制你的调用者处理部分初始化的对象。 请注意,这并不妨碍你在协议中拥有非init配置方法: 如果所有对象必须使用某些信息进行配置,请让你的用户实现任何想要的init,并向你的协议添加一个configureWith:...方法,让你控制配置对象的过程而不知道它的init方法。

这是否是一种正常的做法,即使不是其他人创建实现接口的对象,而是 - SeriousBob
如果您创建了对象,则知道其类型以及它实现的所有协议。在这种情况下,不再需要知道init(或其他任何方法)是协议的一部分。 - Sergey Kalinichenko
好的,那么为什么NSCoding协议有一个initWithCoder:方法? - SeriousBob
@SeriousBob NSCoding 是一个非常特殊的情况:它被设计用于支持归档(在其他框架中也称为“序列化”),因此它在协议中定义了一个 init 方法。实例通过一些反射魔法创建,然后调用 initWithCoder: 方法。其他语言中的框架要求可序列化的类提供一个无参数的构造函数。 - Sergey Kalinichenko
就像我想的一样,感谢您详细的回答。 这意味着对于我来说,在协议中声明init(如果没有被“某些反射魔法”使用)是毫无意义的,并且违反了任何约定,对吗? 问候,Bob - SeriousBob

5

我知道iOS SDK中有一些协议具有init...方法。例如,NSCoding协议具有必需的-initWithCoder:方法。我认为这是正常的做法。


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