自我初始化参数 [英] Self in init params

查看:48
本文介绍了自我初始化参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想像这样使用Self in init参数:

I would like to use Self in init parameters like so:

class A {
    public init(finishBlock: ((_ operation: Self) -> Void)? = nil) {...}
}

我知道我可以在这里使用"A",但是我想实现的是,如果某个类从A继承,那么它的初始化程序将知道操作是它的类类型,而不仅仅是A.所以例如,如果我写道:

I know I could use "A" in this place, but I would like to achieve that if some class inherits from A, then it's initializer would know operation as it's class type and not as just A. So for example if I wrote:

class B: A {
    public init(finishBlock: ((_ operation: Self) -> Void)? = nil) {...}
    public func fooOnlyInB() {}
}

然后我可以使用:

let b = B { (operation) in
    operation.fooOnlyInB()
}

这有可能吗?

推荐答案

代替在每个初始化程序中使用SelfA,您可以简单地覆盖每个子类的初始化程序以使用其自己的类型作为operation

Instead of using Self or A in each of the initialisers, you can simply override each subclass' initialiser to use its own type as operation.

之所以有效,是因为A的初始化程序指出operation应该是符合A的类型,并且当您覆盖它时,您可以自由地使用A的子类作为operation .但是,如果将operation更改为不相关的类型,例如StringInt,则编译器将不会覆盖现有的初始化程序.

This works because A's initialiser states that operation should be a type that conforms to A, and when you override it you have the liberty to use a subclass of A as operation instead. However, if you change operation to an unrelated type such as String or Int, the compiler will not override the existing initialiser.

首先,用init定义A:

class A {
    init(finishBlock: ((_ operation: A) -> Void)?) {...}
}

现在要创建子类,您必须使用子类的类型代替operation覆盖init.在对super.init的调用中,强制向上转换operation($0)为子类的类型,并使用强制转换的operation调用finishBlock.

Now to create a subclass, you must override init using the subclass' type as operation instead. In your call to super.init, force upcast operation ($0) to your subclass' type, and call finishBlock with this casted operation.

class B: A {
    override init(finishBlock: ((_ operation: B) -> Void)?) {
        // Perform custom initialisation...
        super.init { finishBlock?($0 as! B) }
    }

    func fooOnlyInB() {
        print("foo")
    }
}

B的初始化程序现在将B传递为operation,这意味着您不再需要自己转换它!这要归功于您可以使用更具体的类型(在本例中为B)覆盖init.

B's initialiser now passes B as operation, which means that you don't need to cast it yourself anymore! This is thanks to the fact that you can override an init with a more specific type, in this case B.

let b = B { operation in
    operation.fooOnlyInB() // prints "foo"
}

这篇关于自我初始化参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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