自我初始化参数

Dam*_*ycz 5 types initialization swift

我想在init参数中使用Self,如下所示:

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

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

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

然后我可以使用:

let b = B { (operation) in
    operation.fooOnlyInB()
}
Run Code Online (Sandbox Code Playgroud)

这有点可能吗?

kab*_*rai 2

您可以简单地覆盖每个子类的初始化程序以使用其自己的类型作为 ,而不是在每个初始化程序中使用Selfor 。Aoperation

这是有效的,因为A的初始化器声明operation应该是符合 的类型A,并且当您重写它时,您可以自由地使用Aas的子类operation来代替。但是,如果更改operation为不相关的类型(例如String或 )Int,编译器将不会覆盖现有的初始化程序。

首先,定义Ainit

class A {
    init(finishBlock: ((_ operation: A) -> Void)?) {...}
}
Run Code Online (Sandbox Code Playgroud)

现在要创建子类,您必须init使用子类的类型进行重写operation。在对 的调用中super.init,强制向上转换operation( $0) 为子类的类型,并finishBlock使用此强制转换进行调用operation

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

    func fooOnlyInB() {
        print("foo")
    }
}
Run Code Online (Sandbox Code Playgroud)

B的初始化程序现在传递Boperation,这意味着您不再需要自己投射它!这是因为您可以init使用更具体的类型覆盖 an ,在本例中是B.

let b = B { operation in
    operation.fooOnlyInB() // prints "foo"
}
Run Code Online (Sandbox Code Playgroud)