I am trying to create a generic which will create and store objects of type T. However, when i do this it appears that the create function will only create an instance of the constraining type rather than the specified type.
- Is this by design,I believe this used to create the specified type in earlier versions of xcode. Current one in use is 6.3.2?
- How do i get it to create the specified type?
import Foundation
class Base {
var id: Int
init() {
id = 0
println("Initializing base")
}
}
class Derived: Base {
var name: String
override init() {
name = "Undefined"
super.init()
println("Initializing derived")
}
}
class Container<T: Base> {
var collection: [T]
init() {
collection = []
println("Initiazing container with type \(T.self)")
}
func create() -> T {
var newT = T()
println("Created New T() -> \(newT), but should have been \(T.self)")
return newT
}
}
var derivedContainer = Container<Derived>()
var derived = derivedContainer.create()
derived.id = 66 // OK
println("Created type was \(derived)")
//println("Derived name=\(derived.name)") // Thread 1: EXC_BAD_ACCESS(code=2, address=0x1001c5a38)
//derived.name = "wowzer" // Thread 1: EXC_BAD_ACCESS(code=2, address=0x1001d4710)Output, missing Derived initialization:
Initiazing container with type template_test.Derived
Initializing base
Created New T() -> template_test.Base, but should have been template_test.Derived
Created type was template_test.Base
To make this sort of thing work in Swift 1.2 (Xcode 6.3.2), you will probably need to give your Base class a required initializer and store a reference to the type in each container.
class Base {
var id: Int
required init() {
id = 0
println("Initializing base")
}
}
class Derived: Base {
var name: String
required init() {
name = "Undefined"
super.init()
println("Initializing derived")
}
}
class Container<T: Base> {
var elementType: Base.Type
var collection: [T]
init() {
collection = []
elementType = T.self
println("Initiazing container with type \(T.self)")
}
func create() -> T {
let newT = elementType()
println("Created New T() -> \(newT), but should have been \(T.self)")
return newT as! T
}
}
var derivedContainer = Container<Derived>()
var derived = derivedContainer.create()
derived.id = 66 // OK
println("Created type was \(derived)")
println("Derived name=\(derived.name)")
derived.name = "wowzer"The good news is that Swift 2 will work properly with the code in your original post (with minor updates for Swift 2 like print() and T.init()), and create the subclass type declared when creating the container (tested in Xcode 7 beta 2).