覆盖Swift中的超类代理 [英] Overriding a superclass delegate in Swift
问题描述
MyView 有一个委托,我想在MyViewSubclass 中覆盖为一个子协议,类似于 UITableViews 具有一个符合超级UIScrollViewDelegate 的UITableViewDelegate 。
我的第一个想法是覆盖超类属性,但是这个导致编译器错误,因为子类不能覆盖具有不同类型的超类属性。
//示例抛出编译器错误。不能覆盖不同类型的属性
class MyView:UIView {
weak var delegate:MyViewDelegate?
}
class MyViewSubclass:MyView {
override weak var delegate:MyViewSubclassDelegate? //编译器错误
}
协议MyViewDelegate {
func someFunc()
}
协议MyViewSubclassDelegate:MyViewDelegate {
// func someFunc()编辑:redefinition不需要,谢谢@Rob!
func someOtherFunc()
}
我的第二个想法是覆盖隐式getter和setter方法的delegate属性。子类可以有一个getter,它采用一个MyViewSubclassDelegate ,并转换为MyViewDelegate 协议,所以属性本身不需要被覆盖。
此方法也会导致编译器错误。访问器实际上不能覆盖超类方法,因为它们具有不同的方法签名,并且不能被声明,因为它们的名称与超类设置器冲突。
//示例抛出编译器错误。不能声明具有冲突名称的函数
class MyViewSubclass:MyView {
func setDelegate(newValue:MyViewSubclassDelegate){//编译器错误
super.delegate = newValue as? MyViewDelegate
}
func getDelegate() - > MyViewSubclassDelegate {//编译器错误
返回super.delegate为? MyViewSubclassDelegate
}
}
我可以让子类覆盖getter和setter对于超类,并且只将代理存储在一个单独的子类属性中,它的工作,但是这个子类看起来应该被分配一个 MyViewDelegate ,当它真的需要分配一个MyViewSubclassDelegate ,这可能会在将来导致严重的混乱。
//示例工作,但不清楚MyViewSubclass的委托应该是
//分配一个MyViewSubclassDelegate
class MyViewSubclass:MyView {
private weak var _subclassDelegate:MyViewSubclassDelegate?
覆盖weak var delegate:MyViewDelegate? {//模糊类型
didSet {
_subclassDelegate =委托为? MyViewSubclassDelegate
}
}
}
我至少知道一些类似的是可能的,因为像UITableView和UICollectionView这样的类似乎可以做我想要的,但它们也是用Objective-C而不是Swift编写的,所以语言允许的具体细节可能会有所不同。
有没有办法让Swift子类覆盖超类的属性与子类型?
这不是理想的,但是如果一个协议从另一个继承而不是使用不同的类型,则使用相同的类型,但是在 didSet
:
class MyView:UIView {
///MyViewDelegate委托
weak var delegate:MyViewDelegate?
}
class MyViewSubclass:MyView {
///MyViewSubclassDelegate委托。
///
/// **注意:这必须是MyViewSubclassDelegate **
覆盖weak var delegate:MyViewDelegate? {
didSet {
assert(delegate == nil || delegate是MyViewSubclassDelegate,MyViewSubclass的代理必须是MyViewSubclassDelegate类型)
}
}
}
这是不起眼的,但至少你会得到一个立即运行时错误,会带来问题对程序员的注意。通过包含 ///
注释,它也将显示在快速帮助中。
- -
或者您可以采取更激进的更改,例如像委托
和 peoplePickerDelegate
属性 ABPeoplePickerNavigationController
,其中子类委托通过不同的属性指定。
I'm working on a Swift (v1.2) project which contains two UIViews. MyView, and MyViewSubclass .
MyView has a delegate that I want to override in MyViewSubclass to be a sub-protocol, similar to how UITableViews have a UITableViewDelegate which also conforms to the super UIScrollViewDelegate.
My first idea was to override the superclass property, but this causes a compiler error, as a subclass can't override a superclass property with a different type.
// 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 ()
}
My second idea was to override the implicit getter and setter methods of the delegate property. The subclass could have a getter which takes a MyViewSubclassDelegate, and casts down to the MyViewDelegate protocol, so the property itself won't need to be overridden.
This method also results in a compiler error. The accessors can't actually "override" the superclass methods as they have different method signatures, and can't just be declared because their names conflict with the superclass setters.
// 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
}
}
I could have the subclass override the getter and setter for the superclass, and just store the delegate in a separate subclass property, which does work, but then the subclass will look like it should be assigned a MyViewDelegate, when it really needs to be assigned a MyViewSubclassDelegate, which could cause serious confusion in the future.
// 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
}
}
}
I know something at least similar is possible, because classes like UITableView, and UICollectionView seem to do what I want, but they are also written in Objective-C rather than Swift, so the specifics of what the language allows may be different.
Is there any way to have a Swift subclass override a superclass's property with a sub-type?
It's not ideal, but if one protocol is inherited from the other, rather than using different types, use the same type, but implement validation in didSet
:
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`")
}
}
}
It's inelegant, but at least you'll get an immediate runtime error that will bring the problem to the programmer's attention. And by including the ///
comment, it will also be shown in the Quick Help, too.
--
Alternatively you can adopt more radical changes, e.g. something like delegate
and peoplePickerDelegate
properties of ABPeoplePickerNavigationController
, where the subclass delegate is specified via a different property.
这篇关于覆盖Swift中的超类代理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!