我在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];
这似乎是多余的和不必要的。我可能在这里遗漏了一些明显的东西。
答案 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
。