1

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

假设我有三个类 A、B 和 C,它们继承自基类 X。类 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];

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

4

2 回答 2

1

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

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

于 2009-12-16T15:27:19.067 回答
1

我不确定分析器在这些情况下实际上有多聪明,并且怀疑您只是遇到了它的限制之一。

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

解决此问题的一种方法是分两步初始化类:

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

在这种情况下,分析器知道 test 是 ClassA 类型并选择正确的选择器。似乎不太聪明地告诉中间对象是什么类型没有分配给变量,然后总是假设它们是id.

于 2009-12-16T15:37:17.163 回答