一尘不染

自我初始化参数

swift

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

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

我知道我可以在这里使用“ A”,但是我想实现这一点,如果某个类从A继承,那么它的初始化器将知道操作是它的类类型,而不仅仅是A。所以例如,如果我这样写:

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

然后,我可以使用:

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

这可能吗?


阅读 253

收藏
2020-07-07

共1个答案

一尘不染

不必使用SelfA在每个初始化器中使用,您可以简单地重写每个子类的初始化器以使用其自己的类型为operation

之所以起作用,是因为A的初始值设定项声明operation的类型应符合A,并且在您覆盖它时,您可以自由使用Aas
的子类operation。但是,如果更改operation为不相关的类型,例如StringInt,则编译器将不会覆盖现有的初始化程序。

首先,定义Ainit

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

现在要创建一个子类,您必须init改用该子类的类型operation。在对的调用中super.init,将upcast
operation$0)强制为您的子类的类型,然后finishBlock使用cast进行调用operation

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

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

B的初始化器现在可以传递Boperation,这意味着你不需要自己再投吧!这是由于您可以init在这种情况下使用更具体的类型覆盖的事实B

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