从子类setDelegate设置超类委托

时间:2015-01-15 21:46:22

标签: ios objective-c inheritance delegates

我有一个超类A,它具有BaseModalViewControllerDelegate协议和id<BaseModalViewControllerDelegate> delegate的保留属性。 我还有B类,A的子类,它有ModalLoginDelegate协议和id<ModalLoginDelegate> delegate的保留属性

现在,我设置为B类的setter方法委托此方法:

-(void)setDelegate: (id<ModalLoginDelegate>)delegate
{
    _delegate = delegate;
    [super setDelegate: (id<BaseModalViewControllerDelegate>)delegate;
}

因此,有一个RootViewController实现了这两个协议,但它只包含B类,它只将自己设置为B类的委托,因为它不知道B类是A的子类。

您是否认为这是将RootVC设置为两种协议的委托的正确方法?感谢

添加

将B类的协议设置为继承自A类:

@protocol ModalLoginDelegate <BaseModalDelegate>
    // delegate method of subclass
@end

现在,我的RootVC不必将自己设置为BaseModalViewController的委托。但现在,在我的B班中,我想调用超类的委托方法,我这样做

if (self.loginDelegate)
{
    [self.loginDelegate baseModalViewController: self willDismiss: YES];
}

我认为这不是一个非常干净的方式,所以我在超类-(void)pressedCloseButton;中创建了一个公共方法,它将执行此操作

-(void)pressedCloseButton
{
    if (self.delegate)
    {
        [self.delegate baseModalViewController: self willDismiss: YES];
    }
}

在子类中:

-(IBAction)closeBtnPressed: (id)sender
{
    [super pressedCloseButton];
}

你认为是对的吗?

2 个答案:

答案 0 :(得分:3)

更好的设计是为您的子类实现单独的委托属性,比如说loginDelegate。改变子类中属性的类型并不是很好的OO设计。大多数OO语言甚至不允许它。

这也确保了消费类“意识到”涉及两个单独的委托协议。

如果需要实现两种协议,

RootVC将需要将自己设置为两个委托。您不能指望该类不知道它需要实现哪些委托协议。如果RootVC认为它只处理基类,则它不会设置loginDelegate,也不会实现该协议中的方法。

答案 1 :(得分:1)

我根本不同意Paulw11的答案,但有趣的是,Apple自己也这样做了。 例。 UIScrollView具有委托属性

@property (weak, nonatomic) id <UIScrollViewDelegate> delegate;

和子类UITableView具有委托属性

@property (weak, nonatomic) id <UITableViewDelegate> delegate;

当我们在ObjC中声明一个协议时,我们通常会让该协议扩展&lt; NSObject&gt;协议

@protocol BaseModalViewControllerDelegate <NSObject>
-(void)doSomething;
-(NSString *)titleForThing;
@end

现在,上面的这个协议不仅包括这里的原型方法,还包括&lt; NSObject&gt;协议。它非常像这个协议是另一个协议的“子类”,也继承了它的所有东西。

如果您使用第二个协议执行此操作

  @protocol ModalLoginDelegate <BaseModalViewControllerDelegate>
        -(void)doAnotherThing;
        -(NSString *)titleForTheOtherThing;
    @end

那么你在这里所做的将完全符合Apple对UITableView和UIScrollView的所作所为,因为类型为id&lt; ModalLoginDelegate&gt;始终也是id&lt;类型的对象BaseModalViewControllerDelegate&gt; ,就像UIButton *总是能够作为UIView * ...

传递

但是如果没有这样做,你的

就会出现根本问题
 -(void)setDelegate:(id<ModalLoginDelegate>)delegate

方法,因为你假设这个对象符合BaseModalViewControllerDelegate协议,你唯一知道的是它符合ModalLoginDelegate协议。一些继承的方法可能会调用self.delegate与BaseModalViewControllerDelegate方法,self.delegate不会响应.. 我希望这会有所帮助:)