Objective-C继承方法匹配

时间:2009-12-16 14:02:12

标签: objective-c inheritance duck-typing

我在Objective-C中遇到了与类继承相关的奇怪场景。

假设我有三个继承自基类X的A,B和C类。类A,B和X具有构造函数:

- (id)InitWithString:(NSString*)someString andDelegate:(id<SomeProtocol>)aDelegate

唯一的区别是每个类都为委托使用不同的协议。

对于A和B,编译器尝试使用C中的方法。警告通知我C类构造函数所需的协议未由提供的委托实现。委托本身没有任何问题,因为每个类都有一个委托,它为类自己的构造函数实现了正确的协议。在运行时一切正常,并且为所有类调用正确的函数。

我尝试让构造函数返回A *,B *或C *而不是匿名id,尽管这仍然无法解决问题。

唯一有效的方法就是像这样对正确的类进行投射:

instanceOfA = [(A*)[A alloc] InitWithString:@"" andDelegate:aDelegate];

这似乎是多余的和不必要的。我可能在这里遗漏了一些明显的东西。

2 个答案:

答案 0 :(得分:1)

问题在于声明了定义指定类型参数的方法。

您应该使声明尽可能通用,以便对作为最后一个参数传递的对象的所有类有效。 如果所有协议都继承自父协议,那么您可以将该方法声明为- (id)initWithString:(NSString*)someString andDelegate:(id<ParentProtocol>)aDelegate;换句话说,您可以使用更通用的定义- (id)initWithString:(NSString*)someString andDelegate:(id)aDelegate

答案 1 :(得分:1)

我不确定分析仪对于这些情况有多么聪明,并且怀疑你只是遇到了其中一个限制。

您正在观察的是编译器将对象视为id并选择与签名匹配的第一种方法。尝试移动包含类的顺序,你应该看到它总是选择首先定义的选择器。

解决这个问题的方法是分两步初始化类:

ClassA *test = [ClassA alloc];
test = [test initWithString:@"" andDelegate:delegate];

在这种情况下,分析器知道test是ClassA类型并选择正确的选择器。似乎并不是那么聪明,无法分辨哪些类型的中间对象没有分配给变量,然后总是假定它们是id