【发布时间】:2015-10-28 15:25:19
【问题描述】:
我正在开发一个包含两个 UIView 的 Swift (v1.2) 项目。 MyView 和 MyViewSubclass 。
MyView 有一个委托,我想在 MyViewSubclass 中将其覆盖为子协议,类似于 UITableViews 有一个 UITableViewDelegate 也符合超级UIScrollViewDelegate。
我的第一个想法是覆盖超类属性,但这会导致编译器错误,因为子类无法覆盖具有不同类型的超类属性。
// 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 方法。子类可以有一个获取 MyViewSubclassDelegate 的 getter,并强制转换为 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
}
}
}
我知道至少类似的东西是可能的,因为像 UITableView 和 UICollectionView 这样的类似乎可以做我想要的,但它们也是用 Objective-C 而不是 Swift 编写的,所以语言允许的细节可能会有所不同.
有没有办法让 Swift 子类用子类型覆盖超类的属性?
【问题讨论】:
-
感谢您的建议!继承协议将起作用(我在示例中这样做),但它仍然会遇到与示例 3 相同的问题,其中子类的委托看起来好像应该是超级协议,其中子协议委托是必需的。现在,我想我会按照你的第一条评论坚持使用两个单独的参数,直到我找到一个更像 UITableViewDelegate 使用的解决方案。
-
@Rob 也许只是我很难。我对该解决方案的主要抱怨是您不能严格执行协议一致性。如果 MyViewSubclass 具有
MyViewDelegate类型的委托,则无法确保(delegate as? MyViewSubclassDelegate)?.someOtherFunc()将永远执行。视图可以被分配超类,而可选链将默默地失败。你也可以检查它是否响应选择器,但是你有一个运行时约束,而不是编译时。
标签: ios swift inheritance delegates overriding