定义协议中的条件

时间:2011-04-28 15:01:15

标签: objective-c protocols

我有这样的协议:

@protocol ProfileSubObjects <NSObject, NSCoding>
@required
- (BOOL) hasGraph;

@optional
- (NSArray *) xGraphValues;
- (NSArray *) yGraphValues;

如果hasGraph等于YES,我想要这两个可选方法。 有可能吗?

3 个答案:

答案 0 :(得分:1)

不,这是不可能的。至少,不是这样的。然而,存在更深层次的问题。这个问题建议考虑编译与运行时检查和面向对象。

将某些内容标记为@optional或@required意味着您希望执行编译时检查这些对象是否满足提供实现的协议合同 - 或者在@optional的情况下不符合这些方法。

因此,没有理由让编译时检查依赖于运行时变量的值,在本例中为hasGraph。

更好的方法是使用respondsToSelector消息检查。或者,您可以拥有一个具有图形并提供x和y图形值的子类。

答案 1 :(得分:1)

没有。方法要么是协议要求,要么不是。首先,-hasGraph的值在编译时是未知的。因为它是一个实例方法而不是类方法,所以在创建特定对象之前,它甚至在运行时都不知道。此外,对象可能会在不同时间报告-hasGraph的不同值。

这里最好的做法是简单地记录如下事实:如果-hasGraph返回YES,则期望实现-xGraphValues和-yGraphValues。你可以通过抛出异常来强制执行,或者你可以优雅地失败,如果没有实现这些方法,就不会绘制任何数据。使用-respondsToSelector:方法在调用之前检查方法是否已实现。

答案 2 :(得分:0)

那是不可能的; hasGraph的结果只能在运行时知道,而协议的必需/可选部分用于编译器在编译时检查出来。

你可能想要做的是添加一个强烈的注释,如果hasGraph返回YES,那么必须实现xGraphValues和yGraphValues,这会给你的正式协议带来一些不正常的感觉。您可以随时执行以下操作:

if([object respondsToSelector:@selector(xGraphValues)] && 
   [object respondsToSelector:@selector(yGraphValues)])

在运行时验证对象是否实现了所需协议的各个部分,以便能够对其执行特定操作。如果您希望实现不符合对象的人能够通过调试版本找出他们做错了什么,那么将这些东西放在NSAssert中可能是明智的。