覆盖Swift中的超类代理 [英] Overriding a superclass delegate in Swift

查看:138
本文介绍了覆盖Swift中的超类代理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在一个包含两个UIViews的Swift(v1.2)项目。 MyView 和 MyViewSubclass



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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆