Objective-C中的Casting方法参数

Józ*_*sza 2 types casting objective-c ios

更新

好的,首先,谢谢大家的大量活动.似乎我没有把我的问题说得太好,因为许多答案(正确地)都停留在id输入参数上,并且遵循不良的设计模式,但它仅仅是一个例子.我将在我的问题中添加一些上下文:

  • 假设存在多个不同的实现doSomethingWithParameter:,需要特定实例作为输入参数
  • 我的示例中的类只会SpecificClass作为输入参数的实例调用

有了这些断言,这是我的假设:鉴于您知道参数的类型,在类型检查和铸造方面没有任何好处,只是为了更加安全.

原帖

假设我的协议声明中有一个通用方法,它接受一个id输入参数:

@protocol MyProtocol <NSObject>

- (void)doSomethingWithParameter:(id)inputParameter;

@end
Run Code Online (Sandbox Code Playgroud)

在符合的类中MyProtocol,我通常更喜欢将类型inputParameter显式化为:

- (void)doSomethingWithParameter:(SpecificClass *)inputParameter
{
    /... do something with param
}
Run Code Online (Sandbox Code Playgroud)

偶尔我会因为选择此解决方案而受到批评,而不是以下方面:

- (void)doSomethingWithParameter:(id)inputParameter
{
    if ([inputParameter isKindOfClass:[SpecificClass class]]) {
        SpecificClass *myInstance = (SpecificClass *)inputParameter;
        /... do something with param
    }
}
Run Code Online (Sandbox Code Playgroud)

我真的更喜欢第一个版本,因为它清楚地说明了我的实例所期望的参数.它更简洁,更清晰.我通常不认为我可以从类型检查/铸造中获得太多收益.

我的问题:从编码标准的角度来看,哪一个是更好的解决方案?第一个有缺点吗?

Jak*_*ano 5

更新

从更新到您的问题,您似乎正在尝试实现现代语言中泛型提供的功能的某些变体.

由于Objective-C不支持此模式,您可以牺牲类型安全性,或重新考虑您的设计决策.

如果你去了第一种方式,你应该让真正通过其他方式(命名,文件),你期待什么类型的清晰.那么假设你的方法只能用适当的参数调用是合理的.

但我仍然会添加NSParameterAssert以简化将来的调试.


原始答案

如果您使用的是第一种方法,则声明与方法定义之间存在不匹配.由于obj-c的动态特性(方法签名不包括参数类型),编译器不会抱怨它.

但是,在调用方法时,只有声明是可见的,因此有关参数类型的任何信息都是从中派生出来的 - 所有类型检查(是的,这里编译器都是这样)是基于声明来执行的.

总之,为避免混淆错误和滥用API,您绝对应该使用第二种方法.或者将声明与定义一起更改.

编辑

另外,我可以想到第三种解决方案,它将第一种方法的便利性与第二种方法的类型安全性融合在一起:

- (void)doSomethingWithParameter:(SpecificClass *)inputParameter
{
    NSParameterAssert([inputParameter isKindOfClass:[SpecificClass class]]);

    // do something
}
Run Code Online (Sandbox Code Playgroud)