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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With