gpt4 book ai didi

Swift 通用工厂 : Bug?

转载 作者:可可西里 更新时间:2023-11-01 01:06:09 29 4
gpt4 key购买 nike

调查 Swift 泛型,并偶然发现一些非常奇怪的行为……我应该提交一份雷达报告,还是我误解了什么?已使用 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()
}
}

测试,带有非常奇怪行为的屏幕截图(尽管有编译器警告,'is' 测试确实通过了):Compiler warning, and yet the is test passes!!!

// 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 )" )
}
}

最佳答案

这里有两个问题 – 一个是不正确的代码,另一个是已知错误(我的雷达作为 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 被多态调用)导致的错误。

如果您将 required init() { } 添加到 BaseType,您将获得正确的行为。

关于Swift 通用工厂 : Bug?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29500438/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com