【问题标题】:How to define a `Class` object type conforming to a protocol?如何定义符合协议的“Class”对象类型?
【发布时间】:2023-01-19 02:54:53
【问题描述】:

考虑以下 Objective-C 协议声明,它只需要类方法:

@protocol TDWMethoding<NSObject>

+ (void)foo;
+ (void)bar;

@end

假设我需要从方法返回一个符合此协议的 Class 实例,我应该如何指定返回类型?

- (nullable /*return-type*/)instantiateMethoding {
    Class instance = ... // some implementation
    if ([instance conformsToProtocol:@protocol(TDWMethoding)]) {
        return instance;
    }
    return nil;
}

有许多在职的到目前为止,我考虑过关于如何表达 /*return-type*/ 的选项,但每个选项都有其自身的缺点:

  1. Class - 这样它就不会暴露一致性。这是什么Class?它有什么作用?它完全符合协议吗?
  2. Class&lt;TDWMethoding&gt; - 这看起来是一个可行的解决方案,甚至被其他开发人员(herehere)建议过几次,但我个人认为它不一致且具有误导性:当我们有一个形式为Type&lt;Protocol&gt; *instance 的变量时,它通常意味着协议类方法应该发送到实例的类([[instance class] foo])而不是实例本身([instance foo]);
  3. id&lt;TDWMethoding&gt; 并返回一个类的实例 - 这是一致的,但它需要我实例化该类,这既多余又阻止我隐藏符合 NS_UNAVAILABLE 宏协议的实用程序类的构造函数.

    是否有更好的语义来表达这种返回类型?

【问题讨论】:

    标签: objective-c introspection contract objective-c-protocol


    【解决方案1】:

    Class&lt;TDWMethoding&gt; 是正确的。这并不矛盾。当某物是Class 类型时,您向它发送类方法。当某物是一个实例,并且您想发送给类时,您可以访问它的-class

    也就是说,这看起来确实很奇怪,并且可能意味着您过度使用了类方法。您应该认真考虑 sharedInstance 是否是更好的模型。

    但是,如果您想识别类型,Class&lt;TDWMethoding&gt; 是正确的,尽管 id 可能更常见,如 How to cast Class object to conformance witih protocol 中所述。

    【讨论】:

    • 我不是说你错了,但你怎么知道Class&lt;TDWMethoding&gt;id&lt;TDWMethoding&gt;应该有不同的合同?此外,如果Class/objc_class本身就是一个objc_type,您可以对类的元类强加协议一致性,这使得将类方法消息发送到Class&lt;TDWMethoding&gt;实例的元类对象成为可能
    【解决方案2】:

    在深入了解The Objective-C Programming Language documentation 之后,我实际上找到了这种情况的确切答案:

    协议不能用于类型化类对象。只有实例可以静态类型化为协议,就像只有实例可以静态类型化为类一样。 (但是,在运行时,类和实例都会响应 conformsToProtocol: 消息。)

    这意味着它不受支持,我应该以不同的方式实现它。 (例如,使用单例模式,如Rob's answer中所建议)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多