Is it possible to restrict the return type of a function of type Swift to one class or subclass?

I am extending a base class (one that I do not control) in Swift. I want to provide a class function to create an instance injected into a subclass. Common function required. However, an implementation like the one below does not return the expected type of subclass.

class Calculator {
    func showKind() { println("regular") }
}

class ScientificCalculator: Calculator {
    let model: String = "HP-15C"
    override func showKind() { println("scientific") }
}

extension Calculator {
    class func create<T:Calculator>() -> T {
        let instance = T()
        return instance
    }
}

let sci: ScientificCalculator = ScientificCalculator.create()
sci.showKind()

The debugger reports Thow ScientificCalculator, but sci- Calculator, and the call sci.showKind()returns "normal".

Is there a way to achieve the desired result using generics, or is it a mistake?

+4
source share
4 answers

, , , .

class Calculator {
    func showKind() { println("regular") }
    required init() {}
}

class ScientificCalculator: Calculator {
    let model: String = "HP-15C"
    override func showKind() { println("\(model) - Scientific") }
    required init() {
        super.init()
    }
}

extension Calculator {
    class func create<T:Calculator>() -> T {
        let klass: T.Type = T.self
        return klass()
    }
}

let sci:ScientificCalculator = ScientificCalculator.create()
sci.showKind()

, , .

+8

- - :)

, , :

class func create<T:Calculator>() -> T

T , , ScientificCalculator.

. create , T , , :

class func create<T:Calculator>(type: T.Type) -> T

let sci: ScientificCalculator = ScientificCalculator.create(ScientificCalculator.self)

.

: sci ScientificCalculator, Calculator. , :

sci.model

, - model.

: , - ( )

+2

, , . "", init :

class Calculator {
    func showKind() { println("regular") }
    required init() {

    }
}

class ScientificCalculator: Calculator {
    let model: String = "HP-15C"
    override func showKind() { println("scientific") }
}

extension Calculator {
    class func create() -> Self {
        return self()
    }
}

var b = ScientificCalculator.create() // HP-15C
b.showKind()

, , () . .

class Calculator {
    required init() {

    }
    func showKind() { println("regular") }
}

class ScientificCalculator: Calculator {
    let model: String = "HP-15C"
    override func showKind() { println("scientific") }
}

extension Calculator {
    class func create<T:Calculator>( type:T.Type ) -> T {
        return type() as T
    }
    class func newInstance() -> Calculator {
        return self()
    }
}

var b = ScientificCalculator.newInstance() // HP-15C
b.showKind() // sientific
+1
source

This does not explain why your general approach does not work. I'm just looking for an alternative.

Swift seems to have replaced factory methods with convenience initializers. You can create a new convenience initializer and add it with an extension Calculator.

extension Calculator {
    convenience init(name: String) {
        println(name)
        self.init()
    }
}

let reg = Calculator(name: "Reg")
reg.showKind()  // "regular"

let sci = ScientificCalculator(name: "Sci")
sci.showKind()  // "scientific"
0
source

All Articles