更新
好的,首先感谢大家的大量事件。看来我没有很好地表达我的问题,因为许多答案(正确地)停留在 id 输入参数上,并遵循糟糕的设计模式,但这只是一个例子。我将为我的问题添加一些背景信息:
- 假设
doSomethingWithParameter:
有多种不同的实现,需要特定实例作为输入参数 - 示例中的我的类仅会使用
SpecificClass
实例作为输入参数进行调用
根据这些断言,我的假设是:假设您知道参数的类型,类型检查和转换没有任何好处,只是为了额外的安全性。
原帖
假设我的协议(protocol)声明中有一个通用方法,它采用 id
输入参数:
@protocol MyProtocol <NSObject>
- (void)doSomethingWithParameter:(id)inputParameter;
@end
在符合 MyProtocol
的类中,我通常更喜欢将 inputParameter
的类型显式化,如下所示:
- (void)doSomethingWithParameter:(SpecificClass *)inputParameter
{
/... do something with param
}
有时我会因选择此解决方案而受到批评,而不是以下内容:
- (void)doSomethingWithParameter:(id)inputParameter
{
if ([inputParameter isKindOfClass:[SpecificClass class]]) {
SpecificClass *myInstance = (SpecificClass *)inputParameter;
/... do something with param
}
}
我真的更喜欢第一个版本,因为它清楚地说明了我的实例所期望的参数。它更加简洁、清晰。我通常认为我不能从类型检查/转换中获得太多好处。
我的问题:从编码标准的角度来看,哪一个是更好的解决方案?第一个有什么缺点吗?
最佳答案
更新
从您的问题的更新来看,您似乎正在尝试实现现代语言中泛型提供的功能的某些变体。
由于 Objective-C
不支持此模式,因此您可以牺牲类型安全性,或者重新考虑您的设计决策。
如果您采用第一种方式,您应该通过其他方式(命名、文档)真正清楚地表明您期望什么类型。那么可以合理地假设您的方法只会使用正确的参数来调用。
但我仍然会添加 NSParameterAssert
以简化将来的调试。
原始答案
如果您使用第一种方法,则方法的声明和定义之间不匹配。由于 obj-c 的动态特性(方法签名不包括参数类型),编译器不会提示它。
但是,在调用该方法时,只有声明是可见的,因此有关参数类型的任何信息都从中派生 - 所有类型检查(是的,这里是编译器执行的)都是基于声明执行的。
总之,为了避免混淆错误和 API 滥用,您绝对应该使用第二种方法。或者更改声明和定义。
编辑
此外,我可以想到第三种解决方案,它在某种程度上将第一种方法的便利性与第二种方法的类型安全性结合起来:
- (void)doSomethingWithParameter:(SpecificClass *)inputParameter
{
NSParameterAssert([inputParameter isKindOfClass:[SpecificClass class]]);
// do something
}
关于ios - Objective-C 中的方法参数转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30095591/