【问题标题】:Objective C protocols requiring the implementation of at least one of a set of methods需要实现一组方法中的至少一个的 Objective C 协议
【发布时间】:2011-11-06 18:44:36
【问题描述】:

在 Objective C 中,协议方法可以是必需的或可选的:

@protocol AProtocol

@required
-(void) aRequiredMethod;

@optional
-(void) anOptionalMethod;

@end

有没有一种优雅的方式可以说符合协议的对象必须至少响应一组方法中的一个,我的梦想是这样的

@protocol AProtocol

@anyof
-(void) onePossibleMethod;
-(void) anotherPossibleMethod;

@optional
-(void) anOptionalMethod;

@end

编辑:

这(据我所知)是不可能的,如果一个类声明为完全由可选方法组成的给定协议,是否有办法引发编译时警告

@protocol AProtocol

@optional
-(void) onePossibleMethod;
-(void) anotherPossibleMethod;

@end

至少其中一项未能实现。

【问题讨论】:

  • 回复:“编辑”不是我见过的。如果你真的想自动化这个,你可以使用 objc 运行时。

标签: objective-c protocols


【解决方案1】:

在 Objective-C 中没有很好的表达方式。如果你必须这样做,IMO 最惯用和最少代码膨胀的方式是这样的:

@protocol AProtocol

@required
- (SEL)methodToUse; // returns one of "onePossibleMethod" or "anotherPossibleMethod"

@optional
-(void) onePossibleMethod;
-(void) anotherPossibleMethod;
-(void) anOptionalMethod;

@en

【讨论】:

  • 我同意没有什么好办法,但是我确实喜欢您的解决方案,因为它使不熟悉代码的开发人员“正式”(即除了 cmets/documentation),尽管这三种方法是可选,您确实希望实现其中之一。
【解决方案2】:

嗯,你正在使用 ObjC,所以你需要自己保持克制:

@protocol MONAbstractDataProvider
@optional
- (void)anOptionalMethod;
@end

@protocol MONDataProviderA < MONAbstractProvider >
@required
- (void)onePossibleMethod;
@end

@protocol MONDataProviderB < MONAbstractProvider >
@required
- (void)anotherPossibleMethod;
@end

在这种情况下,您必须在呼叫站点进行confromsToProtocol: 测试,而不是respondsToSelector: 测试onePossibleMethodanotherPossibleMethod。然后你传递MONAbstractDataProvider。这可以引入一些类型安全,只要你记住规则,但它实际上只比习惯方法稍微好一点。

所以客户端看起来像这样:

- (void)update:(NSObject<MONAbstractDataProvider>*)provider
{
    if ([provider conformsToProtocol:@protocol(MONDataProviderA)]) {
        [(NSObject<MONDataProviderA>*)protocol onePossibleMethod];
    }
    else if ([provider conformsToProtocol:@protocol(MONDataProviderB)]) {
        [(NSObject<MONDataProviderB>*)provider anotherPossibleMethod];
    }
    else {
        assert(0 && "rule broken");
    }
}

这当然假设客户知道所有的衍生产品。

如果它们都是void,您可能更喜欢更简单的单数方法:

@protocol MONAbstractDataProvider
@required
- (void)performPossibleMethod;
@optional
- (void)anOptionalMethod;
@end

【讨论】:

  • 感谢您的详细回答,这将是一种在运行时进行检查的方法。理想情况下,我想要的是某种会引发警告的编译时检查(我稍微编辑了问题)。
  • @jbat100 嗯 - 我没有把方法的细节说得很清楚。编译时检查进入,因为MONAbstractDataProvider 仅被间接采用。类应该只采用MONDataProviderAMONDataProviderB,而不是直接采用MONAbstractDataProvider
【解决方案3】:

您可以拥有一个动态委托属性,该属性只允许将委托分配给实现一种方法或另一种方法的类——但这是在运行时而不是在编译时。您还可以创建一个 bash 脚本来检查其中一个或另一个是否已实现并且在编译时进行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-01
    • 2014-09-23
    • 1970-01-01
    相关资源
    最近更新 更多