Swift 对协议的泛型转换失败 swift_dynamicCastUnknownClass
Swift generic cast to Protocol fails with swift_dynamicCastUnknownClass
以下示例摘自 Apple Swift 参考指南。我只添加了 getHasAreaInstances() 和 getGenericHasAreaInstances()
import UIKit
@objc protocol HasArea {
var area: Double { get }
}
@objc protocol HasExtendedArea: HasArea {
var extendedArea: Double { get }
}
class Circle: HasArea {
let pi = 3.1415927
var radius: Double
var area: Double { return pi * radius * radius }
init(radius: Double) { self.radius = radius }
}
class Country: HasArea {
var area: Double
init(area: Double) { self.area = area }
}
class Continent: HasExtendedArea {
var area: Double { return 300 }
var extendedArea: Double { return 3000 }
}
let objects: [HasArea] = [
Circle(radius: 2.0),
Country(area: 243_610),
Continent()
]
for object in objects {
if let objectWithArea = object as? HasExtendedArea {
println("Extended Area is \(objectWithArea.area)")
} else {
println("Area is not extended")
}
}
// Extended Area is 300.0
// Area is not extended
// Area is not extended
下面的方法returns正确的数组:
func getHasExtendedAreaInstances() -> [HasExtendedArea] {
var haveArea: [HasExtendedArea] = []
for object in objects {
if let objectWithArea = object as? HasExtendedArea {
haveArea.append(objectWithArea)
}
}
return haveArea
}
let areas = getHasExtendedAreaInstances()
//[Continent]
下面的方法returns正确的数组:
func getGenericHasExtendedAreaInstances<T>() -> [T] {
var haveArea: [T] = []
for object in objects {
if let objectWithArea = object as? T {
haveArea.append(objectWithArea)
}
}
return haveArea
}
let areasGeneric: [HasExtendedArea] = getGenericHasExtendedAreaInstances()
//[Continent]
但是,一旦对泛型类型施加约束,它就不再起作用了
func getGenericConstraintHasExtendedAreaInstances<T: HasArea>() -> [T] {
var haveArea: [T] = []
for object in objects {
if let objectWithArea = object as? T {
// the line above fails with swift_dynamicCastUnknownClass
haveArea.append(objectWithArea)
}
}
return haveArea
}
let areasGenericConstraint: [HasExtendedArea] = getGenericConstraintHasExtendedAreaInstances()
你的泛型函数没有意义。什么可以解决?什么能满足它?使用相同的基本声明结构做一个更简单的例子:这是一个不可能的函数。例如,从这个非泛型函数开始:
class Thing : Printable {
var description : String {return "thing"}
}
func g() -> [Thing] {
return [Thing()]
}
let result : [Thing] = g()
现在将 g
修改为通用的,与您的函数完全平行:
class Thing : Printable {
var description : String {return "thing"}
}
func g<T:Printable>() -> [T] {
return [Thing()]
}
let result : [Thing] = g()
它无法编译 - 因为它没有任何意义。
这在 Swift 1.2 中已修复,已在 Xcode 6.3 Beta 3
上测试
您可以指定类型约束,而 swift 编译器不会对您造成影响
以下示例摘自 Apple Swift 参考指南。我只添加了 getHasAreaInstances() 和 getGenericHasAreaInstances()
import UIKit
@objc protocol HasArea {
var area: Double { get }
}
@objc protocol HasExtendedArea: HasArea {
var extendedArea: Double { get }
}
class Circle: HasArea {
let pi = 3.1415927
var radius: Double
var area: Double { return pi * radius * radius }
init(radius: Double) { self.radius = radius }
}
class Country: HasArea {
var area: Double
init(area: Double) { self.area = area }
}
class Continent: HasExtendedArea {
var area: Double { return 300 }
var extendedArea: Double { return 3000 }
}
let objects: [HasArea] = [
Circle(radius: 2.0),
Country(area: 243_610),
Continent()
]
for object in objects {
if let objectWithArea = object as? HasExtendedArea {
println("Extended Area is \(objectWithArea.area)")
} else {
println("Area is not extended")
}
}
// Extended Area is 300.0
// Area is not extended
// Area is not extended
下面的方法returns正确的数组:
func getHasExtendedAreaInstances() -> [HasExtendedArea] {
var haveArea: [HasExtendedArea] = []
for object in objects {
if let objectWithArea = object as? HasExtendedArea {
haveArea.append(objectWithArea)
}
}
return haveArea
}
let areas = getHasExtendedAreaInstances()
//[Continent]
下面的方法returns正确的数组:
func getGenericHasExtendedAreaInstances<T>() -> [T] {
var haveArea: [T] = []
for object in objects {
if let objectWithArea = object as? T {
haveArea.append(objectWithArea)
}
}
return haveArea
}
let areasGeneric: [HasExtendedArea] = getGenericHasExtendedAreaInstances()
//[Continent]
但是,一旦对泛型类型施加约束,它就不再起作用了
func getGenericConstraintHasExtendedAreaInstances<T: HasArea>() -> [T] {
var haveArea: [T] = []
for object in objects {
if let objectWithArea = object as? T {
// the line above fails with swift_dynamicCastUnknownClass
haveArea.append(objectWithArea)
}
}
return haveArea
}
let areasGenericConstraint: [HasExtendedArea] = getGenericConstraintHasExtendedAreaInstances()
你的泛型函数没有意义。什么可以解决?什么能满足它?使用相同的基本声明结构做一个更简单的例子:这是一个不可能的函数。例如,从这个非泛型函数开始:
class Thing : Printable {
var description : String {return "thing"}
}
func g() -> [Thing] {
return [Thing()]
}
let result : [Thing] = g()
现在将 g
修改为通用的,与您的函数完全平行:
class Thing : Printable {
var description : String {return "thing"}
}
func g<T:Printable>() -> [T] {
return [Thing()]
}
let result : [Thing] = g()
它无法编译 - 因为它没有任何意义。
这在 Swift 1.2 中已修复,已在 Xcode 6.3 Beta 3
上测试您可以指定类型约束,而 swift 编译器不会对您造成影响