adib
adib

Reputation: 8395

Referring to own type in Swift?

When in a class, how to refer to the class itself when declaring closure parameters?

In the example below, what type to place in place of Self so that when constructing Foo, the closure parameter also becomes Foo and similarly for AnotherFoo?

class FooBase {
    init(completionHandler: (_ myself : Self)) {
        // ...
        self.completionHandler = completionHandler
    }

    var completionHandler : ((_ :Self) -> Void)?

    func strategyMethod() { ... }
}

class Foo : FooBase {
    // ...
    override func strategyMethod() {
        // do stuff
        completionHandler?(self)
    }
}

class AnotherFoo : FooBase {
    // ...
    override func strategyMethod() {
        // do other stuff
        completionHandler?(self)
    }
}

func useFoos {
    let foo = Foo(completionHandler: {(me : Foo) in
        // ...
    })
    let anotherFoo = AnotherFoo(completionHandler: {(me : AnotherFoo) in
        // ...
    })
}

Upvotes: 2

Views: 158

Answers (1)

Gary Makin
Gary Makin

Reputation: 3169

I don't think Swift allows you to do what you want, but you can get close.

Use FooBase as the type, but in the closures you pass to the init functions, cast to the type that you know the parameter is:

class FooBase {
    init(completionHandler: @escaping (_ myself : FooBase) -> Void) {
        // ...
        self.completionHandler = completionHandler
    }

    var completionHandler : ((_ myself:FooBase) -> Void)?

    func strategyMethod() {
    }
}

class Foo : FooBase {
    // ...
    override func strategyMethod() {
        // do stuff
        completionHandler?(self)
    }
}

class AnotherFoo : FooBase {
    // ...
    override func strategyMethod() {
        // do other stuff
        completionHandler?(self)
    }
}

func useFoos() {
    let foo = Foo(completionHandler: {(myself_in : FooBase) in
        // This cast should always succeed when the closure is used as intended
        if let myself = myself_in as? Foo {
            // ...
        }
    })
    let anotherFoo = AnotherFoo(completionHandler: {(myself_in : FooBase) in
        // This cast should always succeed when the closure is used as intended
        if let myself = myself_in as? AnotherFoo {
            // ...
        }
    })
}

Upvotes: 1

Related Questions