Objective C重复方法签名

Tom*_*der 1 objective-c

花了很多时间调试这个,我很想知道到底发生了什么!

在一个非常人为的例子中,假设我们有两个对象,Object1有这个方法:

- (void) testMethod:(NSString *)testString
Run Code Online (Sandbox Code Playgroud)

对象2有这种方法:

- (void) testMethod:(NSArray *)testArray
Run Code Online (Sandbox Code Playgroud)

然后,回到Object1,方法中有以下代码:

NSArray *myArray = [[NSArray alloc] init];    
[[[Object2 alloc] init] testMethod:myArray];
Run Code Online (Sandbox Code Playgroud)

当我编译时,Xcode会发出警告:

不兼容的指针类型将'NSArray*'发送到'NSString*'类型的参数

我相信我说出警告是对的,因为我从未实际指定过Object2的类型.将对象显式地转换为Object2可以修复它,但我的问题是:

  1. 在Object2上调用testMethod时,为什么它使用Object1中的方法,当对象彼此无关?
  2. 如果我#import "Object2.h"进入Object1.h而不是Object1.m,为什么警告会消失?

谢谢!

Chu*_*uck 6

当有两个方法具有相同的选择器但签名不同时,编译器必须决定在编译时使用哪个签名 - 因为签名可能会影响生成的代码.不幸的是,编译器是非常愚蠢的,并且它必须通过检查接收器的静态类型来判断使用哪个签名.在这种情况下,无论是allocinit回报id,所以编译器没有任何信息它可以决定你发送此消息的对象类型.所以它基本上是为了打破平局:它闭上眼睛,绕圈旋转了很多次,无论它停止时指向哪个签名,那就是它使用的那个.然后它会根据此随机签名检查您的参数类型,如果猜错了,则认为您传递了错误的类型.

最好的解决方案是避免签名冲突 - 描述性方法名称通常会自行处理,并且为一个或两个选择器添加更多特异性通常是解决您遇到的问题的好方法(例如,制作它testMethodWithName:(NSString *)name).

尽可能静态地输入内容也是个好主意.通常这不是问题,因为您无论如何都想要将新创建的对象分配给变量.在紧要关头,如果将方法的结果赋给变量只是尴尬,你也可以将模糊部分转换为正确的类型,如[(Object2 *)[[Object2 alloc] init] testMethod:myArray].