Исследование Swift generics и спотыкание о каком-то действительно странном поведении ... я должен подать радар, или я что-то не понимаю? Протестировано с бета-версией Swift 1.2.Swift Generic Factory: ошибка?
Кодекс говорит лучшее, простая реализация, которая сдерживает завод в инстанцировании BaseClass и производные классы:
/// Testing factory pattern to instantiate BaseClass and derived
class BaseClassFactory
{
// Always returns an instance of BaseClass, even if the constant or
// variable storing the result is explicitly typed(see test)
class func makeInstance< T : BaseClass >(type: AnyClass) -> T?
{
return T()
}
// Returns an instance of DerivedClass only if the constant or variable storing
// the result is explicitly typed.
class func makeInstanceContrived< T : BaseClass >(type: AnyClass) -> T?
{
let instance : T? = T.makeInstance() as? T
return instance
}
// Works fine
class func makeInstanceAndCallBack< T : BaseClass >(handler: (instance: T?) -> Void) -> Void
{
let myInstance : T? = T.makeInstance() as? T
handler(instance: myInstance)
}
}
class BaseClass
{
// Since T() fails...
class func makeInstance()->BaseClass
{
return BaseClass()
}
}
class DerivedClass : BaseClass
{
override class func makeInstance()->BaseClass
{
return DerivedClass()
}
}
тесты, с скриншотом очень странное поведение (несмотря на предупреждение компилятора, то «есть» тест не проходит) :
// Nope
if let instance = BaseClassFactory.makeInstance(DerivedClass.Type)
{
if instance is DerivedClass == false
{
println("1: Wrong type...")
}
}
// Nope, even when typing the constant. This seems like very dangerous behaviour...
if let instance : DerivedClass = BaseClassFactory.makeInstance(DerivedClass.Type)
{
if instance is DerivedClass == false
{
//compiler even gives a warning here: " 'is' test is always true "
println("2: what the???")
}
}
// Nope
if let contrivedInstance = BaseClassFactory.makeInstanceContrived(DerivedClass.Type)
{
if contrivedInstance is DerivedClass == false
{
println("3: Wrong type...")
}
}
// Yes, typing the constant does the trick here
if let contrivedInstance : DerivedClass = BaseClassFactory.makeInstanceContrived(DerivedClass.Type)
{
println("4: success! type is: \(contrivedInstance)")
}
// Yes
BaseClassFactory.makeInstanceAndCallBack()
{
(instance: DerivedClass?) -> Void in
if let callbackInstance = instance
{
println("5: success! type is: \(callbackInstance)")
}
}
Большое спасибо. Я начал с T.Type в качестве аргумента, за исключением того, что он не работал без требуемого init ... Так как тест 4 прошел, я предположил, что компилятор смог вывести тип в зависимости от AnyClass.Type, который он вроде как кажется (с некоторая помощь). – Gregzo