Swift point variable to init method?

I have a base type and subtypes, like shown below.


class Base {
  init() throws {
  }
}

class Foo : Base {
   override init(data: [UInt8]) throws { }
}

class Bar : Base {
    override init(data: [UInt8]) throws { }
}


And now in my code elsewhere I want to "point" to the initializer. So basically I wanna do something like this illegal code:


func foo(data: [UInt8]) {
    let ptr = ((data: [UInt8]) -> Base) = conditional ? Foo : Bar
    let item = ptr(data: data)
}

Accepted Reply

Your pseudo code seems to be too simpified and the class definitions cannot be compiled. This sort of too simplifed code would lead to a discussion pointing out issues which you might not expect to be discussed:


class Base {
    init() throws {
    }
}
class Foo : Base {
    init(data: [UInt8]) throws {
        try super.init()
    }
}
class Bar : Base {
    init(data: [UInt8]) throws {
        try super.init()
    }
}


And your example seems also to be too simplified and many readers would think why you would not do it in this simple way:


func foo(data: [UInt8]) {
    do {
        let item = try conditional ? Foo(data: data) : Bar(data: data)
        print(item)
        //...
    } catch {
        print(error)
        //...
    }
}


But, anyway, when you want to get initializers as closure, you can use `.init`:


func foo(data: [UInt8]) {
    let closure: ((_ data: [UInt8]) throws -> Base) = conditional ? Foo.init : Bar.init
    do {
        let item = try closure(data)
        print(item)
        //...
    } catch {
        print(error)
        //...
    }
}

Replies

Your pseudo code seems to be too simpified and the class definitions cannot be compiled. This sort of too simplifed code would lead to a discussion pointing out issues which you might not expect to be discussed:


class Base {
    init() throws {
    }
}
class Foo : Base {
    init(data: [UInt8]) throws {
        try super.init()
    }
}
class Bar : Base {
    init(data: [UInt8]) throws {
        try super.init()
    }
}


And your example seems also to be too simplified and many readers would think why you would not do it in this simple way:


func foo(data: [UInt8]) {
    do {
        let item = try conditional ? Foo(data: data) : Bar(data: data)
        print(item)
        //...
    } catch {
        print(error)
        //...
    }
}


But, anyway, when you want to get initializers as closure, you can use `.init`:


func foo(data: [UInt8]) {
    let closure: ((_ data: [UInt8]) throws -> Base) = conditional ? Foo.init : Bar.init
    do {
        let item = try closure(data)
        print(item)
        //...
    } catch {
        print(error)
        //...
    }
}

Thanks. It ends up looking like so:



        let constructor: ((_ data: [UInt8]) throws -> AbstractFrame)
        switch type {
        case .continuation:
            constructor = ContinuationFrame.init
        case .data:
            constructor = DataFrame.init
        case .goAway:
            constructor = GoAwayFrame.init
        case .headers:
            constructor = HeadersFrame.init
        case .ping:
            constructor = PingFrame.init
        case .priority:
            constructor = PriorityFrame.init
        case .pushPromise:
            constructor = PushPromiseFrame.init
        case .rstStream:
            constructor = RstStreamFrame.init
        case .settings:
            constructor = SettingsFrame.init
        case .windowUpdate:
            constructor = WindowUpdateFrame.init
        }