我正在开发一个包含两个 UIView 的 Swift (v1.2) 项目。 MyView 和 MyViewSubclass 。
MyView 有一个委托(delegate),我想在 MyViewSubclass 中将其覆盖为一个子协议(protocol),类似于 UITableViews 有一个 UITableViewDelegate 也符合 super UIScrollViewDelegate。
我的第一个想法是覆盖父类(super class)属性,但这会导致编译器错误,因为子类无法覆盖具有不同类型的父类(super class)属性。
// 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 ()
}
我的第二个想法是覆盖委托(delegate)属性的隐式 getter 和 setter 方法。子类可以有一个接受 MyViewSubclassDelegate 的 getter,并向下转换为 MyViewDelegate 协议(protocol),因此属性本身不需要被覆盖。
此方法也会导致编译器错误。访问器实际上不能“覆盖”父类(super class)方法,因为它们具有不同的方法签名,并且不能只是声明,因为它们的名称与父类(super class) setter 冲突。
// 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
}
}
我可以让子类覆盖父类(super class)的 getter 和 setter,并将委托(delegate)存储在一个单独的子类属性中,它确实有效,但是子类看起来应该被分配一个 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
}
}
}
我知道至少类似的东西是可能的,因为像 UITableView 和 UICollectionView 这样的类似乎可以做我想做的,但它们也是用 Objective-C 而不是 Swift 编写的,所以语言允许的细节可能不同.
有没有办法让 Swift 子类用子类型覆盖父类(super class)的属性?
最佳答案
这并不理想,但如果一个协议(protocol)是从另一个协议(protocol)继承的,而不是使用不同的类型,使用相同的类型,但在 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`")
}
}
}
虽然不够优雅,但至少您会立即得到一个运行时错误,从而引起程序员的注意。通过包含 ///
注释,它也将显示在快速帮助中。
--
或者,您可以采用更彻底的更改,例如类似于 ABPeoplePickerNavigationController
的 delegate
和 peoplePickerDelegate
属性,其中子类委托(delegate)是通过不同的属性指定的。
关于ios - 在 Swift 中覆盖父类(super class)委托(delegate),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31839512/