【发布时间】:2012-03-19 04:27:19
【问题描述】:
在对类进行子类化时,我还想对父类的委托进行子类化,因为子类现在具有附加功能。这样做的最佳方法是什么?如果我只是在子类中声明另一个具有相同名称的委托属性,我会收到警告“属性类型 'id' 与继承自 'ParentClass' 的类型 'id' 不兼容
【问题讨论】:
在对类进行子类化时,我还想对父类的委托进行子类化,因为子类现在具有附加功能。这样做的最佳方法是什么?如果我只是在子类中声明另一个具有相同名称的委托属性,我会收到警告“属性类型 'id' 与继承自 'ParentClass' 的类型 'id' 不兼容
【问题讨论】:
鉴于这个产生警告的例子:
// Class A
@protocol ClassADelegete;
@interface ClassA : NSObject
@property (nonatomic, weak) id<ClassADelegete> delegate;
@end
@protocol ClassADelegete <NSObject>
- (void)classADidSomethingInteresting:(ClassA *)classA;
@end
// Class B
@protocol ClassBDelegete;
@interface ClassB : ClassA
@property (nonatomic, weak) id<ClassBDelegete> delegate; // Warning here
@end
@protocol ClassBDelegete <ClassADelegete>
- (void)classBDidSomethingElse:(ClassB *)classB;
@end
消除警告的两种解决方案是。
1) 在子类中,将协议定义放在类定义之前。这就是UITableViewDelegate in UITableView.h 所做的:
// Class B
@class ClassB;
@protocol ClassBDelegete <ClassADelegete>
- (void)classBDidSomethingElse:(ClassB *)classB;
@end
@interface ClassB : ClassA
@property (nonatomic, weak) id<ClassBDelegete> delegate;
@end
2) 在子类中,在新协议旁边添加原始协议:
// Class B
@protocol ClassBDelegete;
@interface ClassB : ClassA
@property (nonatomic, weak) id<ClassADelegete, ClassBDelegete> delegate;
@end
@protocol ClassBDelegete <ClassADelegete>
- (void)classBDidSomethingElse:(ClassB *)classB;
@end
我假设 (1) 像 Apple 那样工作,选项 (2) 删除了警告,但我还没有编译和运行任何以这种方式设置的东西。
【讨论】:
以NSTableView 和NSOutlineView 为例。
NSOutlineView 是 NSTableView 的子类,并为其dataSource 和delegate 定义了自己的协议。
NSTableView 这样声明它的委托:
- (void)setDelegate:(id <NSTableViewDelegate>)delegate;
- (id <NSTableViewDelegate>)delegate;
和NSOutlineView:
- (void)setDelegate:(id <NSOutlineViewDelegate>)anObject;
- (id <NSOutlineViewDelegate>)delegate;
显然编译器对裸方法声明比对属性声明更宽松。
与 NSTable/OutlineView 不同,您可能希望使子类的协议继承自基类的协议,例如
@protocol SpecializedProtocol <BaseProtocol>
...这可能取决于情况。
【讨论】: