如何从超类创建子类的实例数组

时间:2015-03-05 22:22:33

标签: swift

this answer开始,我知道我可以从超类创建一个子类的实例。然而,我无法弄清楚如何从超类中创建子类的数组。

借鉴上面的例子,到目前为止,这是我最好的镜头:

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 createMultiple<T:Calculator>(num: Int) -> T {
        let subclass: T.Type = T.self
        var calculators = [subclass]()
        for i in 0..<num {
            calculators.append(subclass())
        }
        return calculators
    }
}

let scis: [ScientificCalculator] = ScientificCalculator.createMultiple(2)
for sci in scis {
    sci.showKind()
}

使用该代码,行var calculators = [subclass]()会显示错误Invalid use of '()' to call a value of non-function type '[T.Type]'

如何从Calculator.createMultiple返回一系列ScientificCalculators?

2 个答案:

答案 0 :(得分:2)

编辑:在最新的Swift 1.2测试版中,此行为似乎已发生变化。您不应该使用T.selfT是您要创建的类型。但是如果你使用1.1,它似乎不起作用(即使T是子类型,它创建超类型),并使用元类型来创建类型解决此问题。请参阅1.1版本的答案结尾。

您不需要弄乱subclass: T.Type = T.self。只需使用T - 它本身就是类型(或者更确切地说,是调用者指定的任何类型的占位符):

extension Calculator {
    // you meant to return an array of T, right?
    class func createMultiple<T: Calculator>(num: Int) -> [T] {
        // declare an array of T
        var calculators = [T]()
        for i in 0..<num {
            // create new T and append
            calculators.append(T())
        }
        return calculators
    }
}

顺便说一句,你可以用map替换for循环:

class func createMultiple<T: Calculator>(num: Int) -> [T] {
    return map(0..<num) { _ in T() }
}

如果您仍在使用Swift 1.1,则需要使用T.self来解决未正确创建子类型的问题:

extension Calculator {
    // only use this version if you need this to work in Swift 1.1:
    class func createMultiple<T: Calculator>(num: Int) -> [T] {
        let subclass: T.Type = T.self
        return map(0..<num) { _ in subclass() }
    }
}

答案 1 :(得分:2)

你走在正确的轨道上,但你犯了一些错误。

首先,您需要返回T的数组,而不仅仅是单个元素。因此,您需要将返回类型从T更改为[T]

class func createMultiple<T:Calculator>(num: Int) -> [T] {

您也可以使用T初始化子类的新实例,如下所示:

var calculators:[T] = [T]()

但其他部分是正确的。所以你的最终方法看起来像那样:

extension Calculator {
    class func createMultiple<T:Calculator>(num: Int) -> [T] {
        let subclass: T.Type = T.self
        var calculators = [T]()
        for i in 0..<num {
            calculators.append(subclass())
        }
        return calculators
    }
}

修改 如果您使用的是Swift 1.2,则不必再处理subclass,您可以使用T代替Airspeeds中的答案。

calculators.append(T())