【问题标题】:Objective C protocols usageObjective C 协议的使用
【发布时间】:2011-10-01 01:45:23
【问题描述】:

我有一个家庭作业问题让我很困惑,非常糟糕。下面是一个问题的简要说明。

假设您正在开发一个存储联系人的应用程序 信息。地址簿可能包含许多实体类型,例如人类 是,公司或任何其他有联系信息的东西。

  • 现在不再显式检查每个对象类型,而是编写一个 声明对象必须如何表现和成功的协议 出现在您的通讯录中。

我回答这个问题的理解和努力是,

  1. 构建一个协议,在@required标签下对各类联系信息有通用方法。以及@optional下的所有其他在不同联系人中不相似的方法(例如传真号码与公司相关但与人无关......)。在运行时,您可以使用selector 检查对象是否响应任何给定的方法。 怀疑:但是这又是间接地显式检查对象类型,对吗?

  2. 我的第二个想法是在 java 中使用类似 abstract class 的东西。这意味着从抽象类继承的类实现了自己的抽象方法。作为一个天真的 iOS 开发人员,我怎么不知道如何实现呢?我不确定这是否能解决我的问题。如果有人知道这一点,我希望得到启发。


到目前为止完成的外部阅读,如果我正在寻找的答案在这些链接之一中,请告诉我。我会再读一遍以理解和解决这个问题:)。谢谢。

  1. http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProtocols.html#//apple_ref/doc/uid/TP30001163-CH15-TPXREF144

  2. http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProtocols.html#//apple_ref/doc/uid/TP30001163-CH15-TPXREF146

  3. http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProtocols.html#//apple_ref/doc/uid/TP30001163-CH15-TPXREF149

【问题讨论】:

标签: objective-c ios protocols typechecking


【解决方案1】:

协议与 Java 接口相同。它只是定义了类应该支持的方法。这是一个解释清楚的页面:http://www.otierney.net/objective-c.html#protocols

基本上,如果你想确保一个类有一个phoneNumber 方法(phoneNumber 属性的访问器),你可以这样做:

@protocol ContactProtocol
-(void) phoneNumber;
@end

@interface Person: NSObject <ContactProtocol> {
    ...
}

@interface Company: NSObject <ContactProtocol> {
    ...
}

然后在编译时(或适用于 xcode 4)它会告诉你是否忘记将 phoneNumber 方法添加到 PersonCompany 类中。

【讨论】:

  • 协议与抽象类不同;相反,它们类似于 Java 中的接口。当您从抽象类派生类时,您继承了方法及其实现。使用接口,您只能获得声明。 Obj-c 协议也是如此——当你声明一个类实现了一个协议时,你必须提供方法实现。
  • 你是绝对正确的。我在考虑接口!我正在更新我的答案。
  • Otierney.net 的链接目前已关闭。这是谷歌缓存的链接,不知道它能工作多长时间。 webcache.googleusercontent.com/…
【解决方案2】:

不过,这又是在间接地显式检查对象类型,对吗?

不,检查行为与检查类型不同。您可以将-respondsToSelector: 发送到任何对象,如果结果为“是”,则无论对象的类型如何,您都可以发送消息。你也可以要求一个对象实现一个给定的协议,同样不关心它的实际类型:

id<SomeProtocol> foo;  // foo points to any type that implements SomeProtocol

我的第二个想法是在 java 中使用抽象类之类的东西。

这可能行得通,但这显然不是你的任务所要求的,对吧?它说“......编写协议......”

Objective-C 没有像 Java 那样提供显式抽象类的方法。您只需创建类,如果您不想直接实例化它,您可以在某处记录它。

【讨论】:

  • 这个问题与 Swift 无关,但如果是这样,如果我错了,请纠正我:你的第一个答案是:是的,现在在 Swift 中,协议是一种类型,只是你做delegate?.someMethod 虽然与respondsToSelector 不同,但如果设置了委托,它将运行该函数...第二个问题:(在阅读您对已接受答案的评论后)在 Swift 中,因为您还可以为协议提供很多默认实现像抽象类。
  • @Honey 这个答案早于 Swift,应该在这种情况下阅读。我的评论也是如此。即使问题和答案与 Swift 是同时期的,问题的标题清楚地说“Objective-C”并且问题被标记为objective-c
  • 我真的知道,我只是在询问它与 Swift 的差异,这个主题有答案,我只是在检查我是否能够将所有内容放在一起(尤其是与您上面的评论一起)正确。
【解决方案3】:

你有……选项。

可选方法便于编写类的人遵守协议,但对使用协议的人来说很烦人。所以这取决于你想取悦谁。

可选方法没有检查类型那么糟糕。想象一下代码在访问可联系实体对象时的样子。当你使用可选方法时,你必须有一个 if case 和一个 else case。这不像继续假设您可以调用该方法那么方便。但这比检查类型更方便。对于每种不同类型的实体,这将是一个 if 案例(以及一个 else 案例,它可能是一个断言)。此外,如果您使用可选方法,则有关实体的信息将封装在其类中。如果您在调用方法之前检查类型,则有关实体提供的联系信息类型的信息在调用代码中的类之外。如果您升级实体以提供其他类型的联系人,则在您更新调用代码之前,该改进不可用。

选项 B 是使所有方法都需要,但给它们一个选项,即返回一个表明没有可用信息的值,例如 nil。当然,这仍然意味着检查 nil 结果的 if 情况,它只是不那么冗长。对于这个问题,一个更好的解决方案是让这些方法返回多个联系人的集合。毕竟,人们可以拥有多个电话号码。然后,为了表明某个联系人类型不适用,您只需返回一个空集合。

缺点是编写符合协议的类的人必须添加一个简单的存根方法,上面写着return nil 或其他东西。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-10
    • 2014-12-15
    • 2011-06-05
    • 2011-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多