在Swift中重载一个超类委托

我正在做一个包含两个UIViews的Swift(v1.2)项目。 MyViewMyViewSubclass

MyView有一个代理 ,我想在MyViewSubclass中重写成一个子协议,类似于UITableViews有一个UITableViewDelegate也符合超级UIScrollViewDelegate

我的第一个想法是重写超类属性,但这会导致编译器错误 ,因为子类不能重写具有不同types的超类属性。

// Example throws a compiler error. Can't override property with different type class MyView : UIView { weak var delegate : MyViewDelegate? } class MyViewSubclass : MyView { override weak var delegate : MyViewSubclassDelegate? // Compiler error } protocol MyViewDelegate { func someFunc () } protocol MyViewSubclassDelegate : MyViewDelegate { //func someFunc () Edit: redefinition not necessary, thanks @Rob! func someOtherFunc () } 

我的第二个想法是重写委托属性的隐式getter和setter方法。 子类可以有一个getter,它接受一个MyViewSubclassDelegate ,并转换成MyViewDelegate协议,所以属性本身不需要被覆盖。

这种方法也会导致编译器错误 。 访问者实际上不能“覆盖”超类方法,因为它们具有不同的方法签名,不能仅仅因为它们的名字与超类设置者冲突而被声明。

 // Example throws a compiler error. Can't declare function with a conflicting name class MyViewSubclass : MyView { func setDelegate ( newValue : MyViewSubclassDelegate ) { // Compiler error super.delegate = newValue as? MyViewDelegate } func getDelegate () -> MyViewSubclassDelegate { // Compiler error return super.delegate as? MyViewSubclassDelegate } } 

我可以让子类覆盖超类的getter和setter,并将代理存储在一个单独的子类属性中, 属性可以工作 ,但是当子类真的需要分配时,子类看起来应该被分配一个MyViewDelegate一个MyViewSubclassDelegate ,这可能会在未来造成严重的困惑。

 // Example works, but it is unclear that MyViewSubclass's delegate should be // assigned a MyViewSubclassDelegate class MyViewSubclass : MyView { private weak var _subclassDelegate : MyViewSubclassDelegate? override weak var delegate : MyViewDelegate? { // Ambiguous type didSet { _subclassDelegate = delegate as? MyViewSubclassDelegate } } } 

我知道至less类似的东西是可能的,因为像UITableView和UICollectionView类似乎做我想做的,但他们也写在Objective-C而不是Swift,所以语言允许的具体细节可能是不同的。

有什么办法让一个Swift子类重写一个子types的超类的属性?

这并不理想,但是如果一个协议是从另一个inheritance的,而不是使用不同的types,则使用相同的types,但是在didSet实现validation:

 class MyView : UIView { /// The `MyViewDelegate` delegate weak var delegate: MyViewDelegate? } class MyViewSubclass: MyView { /// The `MyViewSubclassDelegate` delegate. /// /// **Note: This must be MyViewSubclassDelegate** override weak var delegate: MyViewDelegate? { didSet { assert(delegate == nil || delegate is MyViewSubclassDelegate, "The delegate of MyViewSubclass must be of type `MyViewSubclassDelegate`") } } } 

这是不雅的,但至less你会得到一个即时的运行时错误,将问题的程序员的注意力。 通过包含///注释,它也将显示在快速帮助中。

或者,您可以采用更激进的更改,例如像ABPeoplePickerNavigationController delegatepeoplePickerDelegate属性,其中子类委托通过其他属性指定。