Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
536 views
in Technique[技术] by (71.8m points)

swift - Self in init params

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

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

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() {}
}

I could then use:

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

Is this somehow possible?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.

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.

Firstly, define A with its init:

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

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'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"
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...