2014-06-21 3 views
4

Я не уверен, как, если это возможно, написать метод, который вызывает конструктор его общего типа, наследующего от общего известного базового класса < T: Base>, чтобы создать некоторые экземпляры T, не прибегая к явной фабричной функции, то есть со всеми колокольчиками и свистки, предоставляемые по типу вывода.Как написать общий метод фабрики в быстром?

Пример, который работает в детской площадки:

// Let there be classes MyPod and Boomstick with common Base (not important) 
class Base : Printable { 
    let value : String; init(_ value : String) { self.value = "Base." + value } 
    var description: String { return value } 
} 
class MyPod : Base { 
    init(_ value: String) { super.init("MyPod." + value) } 
} 
class Boomstick : Base { 
    init(_ value: String) { super.init("Boomstick." + value) } 
} 
// PROBLEM: do not know how to force call of Boomstick(n) instead of Base(n) in here 
func createSome<T : Base>() -> T[] { 
    var result = Array<T>() 
    for n in 1...5 { 
     result += T(toString(n)) 
    } 
    return result 
} 
// This seems to be fine. 
// I was expecting call of createSome<Boomstick>() { ... result += Boomstick(n) ... 
let objs : Boomstick[] = createSome() 
// Prints: Base.1, Base.2, ... not much wished Boomstick.1, Boomstick.2, ... 
println(objs) 

Одно очевидное решение делегировать создание вызывающей, но это, кажется неуклюжим:

func createSome<T>(factory : (Int)->T) { ... } 

Спасибо.

PS: Не назначает createSome() -> Base [] для objs: Boomstick [] нарушение безопасности типа?

+0

Возможный дубликат [Swift generics не сохраняющий тип] (http://stackoverflow.com/questions/26280176/swift-generics-not-preserving-type) – Lee

ответ

4

Прямо сейчас у меня нет ответа о почему, но определяющий протокол с инициализаторе только кажется, работает:

protocol A { 
    init(_ value: String) 
} 

Вы реализуете этот протокол во всех классах, как показано ниже

class Base : Printable, A { 
    let value : String; 
    init(_ value : String) { self.value = "Base." + value } 
    var description: String { return value } 
} 

class MyPod : Base, A { 
    init(_ value: String) { super.init("MyPod." + value) } 
} 

class Boomstick : Base, A { 
    init(_ value: String) { super.init("Boomstick." + value) } 
} 

и использовать A, а не Base в вашем createSome() FUNC

func createSome<T : A>() -> [T] { 
    var result = Array<T>() 
    for n in 1...5 { 
     result += T(toString(n)) 
    } 
    return result 
} 

Испытано в детской площадке:

let objs : [Boomstick] = createSome() 
objs[0] 

и печатает:

{value "Base.Boomstick.1"} 

пытался также с помощью MyPod и Base и напечатанное ожидаемых результатов. Протестируйте это и сообщите мне, если это сработает и для вас.

+0

Это больше не работает. См. Http://stackoverflow.com/questions/26280176/swift-generics-not-preserving-type – Lee

+0

Это на самом деле неплохо. Он может быть даже использован в интересах: продвигать базовый класс в протокол => меньше наследования, более выражать то, что выглядит как ... Спасибо! ... и черт возьми (второй пост) ... :-D – Adam

+0

Взгляните на: https://gist.github.com/joshdholtz/251b02730edd52330cee –

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