【问题标题】:Objective-C Class keyword and ProtocolsObjective-C 类关键字和协议
【发布时间】:2013-09-02 19:54:38
【问题描述】:

如果你尝试混合类和协议,在 Objective-C 中意味着什么?如果类不符合协议,我试图让编译器在编译器时警告我。例如:

@protocol FLLiveDataProtocol <NSObject>
...
@end

- (id)initWithDataPath:(NSString *)path usingDataClassFactory:(Class<FLLiveDataProtocol>)dataFactoryClass;

但是,当我尝试这个时,我遇到了各种有趣的问题。首先,如果您传入一个不符合协议的类,它不会触发编译器错误,其次,如果您尝试执行 [[dataFactoryClass] alloc] init] 即使通过协议也符合 NSObject。

我没有看到很多人试图混合协议和 Class 关键字的例子(我应该说 Typedef -- 感谢 Nikolai)。

我知道我可以使用 conformsToProtocol 在运行时检查,但如果我能在编译时检查它会很好。

【问题讨论】:

  • 实际上,conformsToProtocol 在运行时甚至不会告诉你——因为你需要在每个相关方法上执行 respondsToSelector。 (这是“鸭子打字”的背面——知道它不是鸭子的唯一方法是注意它看起来不像鸭子、走路或嘎嘎声。)
  • 我认为您试图解决错误的问题。为什么你的数据工厂必须是一个类?如果你是一个实例会容易很多吗?
  • 我使用的是标准工厂模式,因为我需要它根据给定的工厂类创建多个实例。
  • 我在协议中使用了@required 关键字(上面没有显示),所以如果它没有实现预期的方法,我会得到一个编译时错误。这让我在使用 conformsToProtocol 时感到相当舒适。

标签: objective-c


【解决方案1】:

Objective-C (see this question) 中没有类对象的静态类型信息,因此无法表示类需要符合协议。

旁注:Class 不是关键字,而是 objc.h 中的 typedef:

typedef struct objc_class *Class;

【讨论】:

  • 你知道语法 Class 对编译器意味着什么吗?使用该语法时不会出错。
  • 它就像id&lt;FLLiveDataProtocol&gt;,只是它会在传入已知不是类的东西(例如NSArray *&lt;FLLiveDataProtocol&gt;)时发出警告。
【解决方案2】:

第二个你会得到诸如“不知道选择器的类方法”之类的错误 alloc" 如果您尝试执行 [[dataFactoryClass] alloc] init] 甚至通过 该协议符合 NSObject。

原因是您的协议或NSObject protocol 都没有声明+alloc。您可以通过在协议声明中添加+alloc 方法(或其他返回新实例的类方法)来解决此问题。

【讨论】:

  • 哇,这真的很有趣。我曾假设 alloc 将由 NSObject 定义。我需要阅读有关 ObjC 运行时的更多信息。 Alloc 由 NSProxy 类实现,该类使用属性将自身附加到 NS_ROOT_CLASS。很有意思。我将不得不尝试在协议中定义一个 alloc 方法,看看会发生什么。
  • 不确定为什么您认为 Obj-C 运行时与此处相关。 +allocclass NSObject 实现(并且独立地由 NSProxy 类实现),它只是没有在 NSObject 协议中声明(它们都符合)。很可能您的类确实实现了 +alloc,但静态类型 Class&lt;MyProtocol&gt; 不会将其传达给编译器。
  • 虽然我同意,但奇怪的是 NSObject 协议没有声明它。
猜你喜欢
  • 2011-07-07
  • 2011-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多