调查斯威夫特的仿制品,并绊倒一些非常奇怪的行为......我应该提交雷达,还是我在这里误解了什么?使用Swift 1.2测试版进行测试。
代码说得最好,简单的实现限制了工厂实例化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 )" )
}
}
答案 0 :(得分:3)
这里有两个问题 - 一个是错误的代码,另一个是已知的错误(我的雷达被关闭为18518629的副本,从1.2b4开始仍然打开)。
首先,在这个结构中:
class func makeInstance< T : BaseClass >( type: AnyClass ) -> T?
{
return T()
}
// then later
BaseClassFactory.makeInstance( DerivedClass.Type )
你的论点没有做任何事情。它本质上毫无意义,并没有对T
的类型做出贡献(怎么可能?参数不引用T
)。相反,T
的类型将从上下文中选择,即如果您将结果分配给DerivedClass
变量,则T
将为DerivedClass
。如果您没有指定,则默认行为是将T
约束为BaseClass
的基类。
你可能的意思是:
class func makeInstance< T : BaseClass >( type: T.Type ) -> T?
{
return T()
}
// then later
BaseClassFactory.makeInstance( DerivedClass.self )
这应该可以将T
设置为您想要的类型。除了它仍然没有工作,因为基类没有动态调度的初始化器导致的错误(通用只有一个运行时实现,它依赖于多态称为正确的init)。 / p>
如果您将required init() { }
添加到BaseType
,您将获得正确的行为。