如何正确地在Objective-C中对委托属性进行子类化?

11
在继承一个类时,我想同时继承父类的代理(delegate),因为子类现在有了额外的功能。如何最好地实现这样的操作?如果我只是在子类中声明另一个同名的代理属性,那么我将会收到警告:“属性类型'id'与从'ParentClass'继承的类型'id'不兼容”。
2个回答

20

考虑以下例子,它会产生警告:

// 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)在子类中,在类定义之前放置协议定义。这就是UITableView.h中的UITableViewDelegate所做的:

// 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)可行,因为苹果也是这样做的。选择(2)可以消除警告,但我没有编译和运行使用这种方式设置的任何内容。

也许有点晚了,但是同样的例子怎么样,只有ClassADelegete和ClassBDelegete是用Swift编写的,而ClassA和ClassB仍然使用Objective C?在这种情况下,我无法消除警告。 - Eduard
选项(1)可行,但我们还需要在ClassB中添加@dynamic delegate; - boog

2

跟随 NSTableViewNSOutlineView 的例子。

NSOutlineView 是 NSTableView 的子类,并为其 dataSourcedelegate 定义了自己的协议。

NSTableView 通过以下方式声明其代理:

- (void)setDelegate:(id <NSTableViewDelegate>)delegate;
- (id <NSTableViewDelegate>)delegate;

以及 NSOutlineView:

- (void)setDelegate:(id <NSOutlineViewDelegate>)anObject;
- (id <NSOutlineViewDelegate>)delegate;

显然,编译器对于裸方法声明比属性声明更宽容。

与NSTable/OutlineView不同,您可能希望使子类的协议继承自基类的协议,例如:

 @protocol SpecializedProtocol <BaseProtocol>

这可能取决于情况。


我选择了后一种方法(在子类化主类之后再子类化委托协议),但是无法声明另一个委托属性而不触发编译器错误。你提到的方法声明是让编译器满意的唯一方式吗? - Boon
我不知道还有其他的方法来做这件事。 - Kurt Revis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接