2015-03-05 2 views
0

От 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]'.

Как я могу вернуть массив ScientificCalculators от Calculator.createMultiple?

ответ

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 вместо как показаны в ответе воздушных скоростей ,

calculators.append(T()) 
2

EDIT: похоже, это поведение изменилось в последней версии Swift 1.2. Вам не нужно использовать T.self. T - тип, который вы хотите создать. Но если вы используете 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 
    } 
} 

Кстати, вы можете заменить эту 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

Я думаю, что код не создает ScienceCalculator, а обычные объекты Calculator. – Christian

+0

@ChristianWoerz no, он создает все, что есть T –

+0

Если я попробую ваш код на Playground, он создаст обычный калькулятор, если я вызову функцию из класса ScienceCalculator, как это сделал OP. – Christian

Смежные вопросы