我遇到了非常奇怪的行为,我真的无法做出正面或反面的行为。我试图在类数组中存储类类型,并希望稍后调用,但它不起作用。这是我的代码
class BaseClass {
class func getDetails() -> String {
return "aaaaaa"
}
}
class Foo: BaseClass {
override class func getDetails() ->String {
return "foo"
}
}
class Bar: BaseClass {
override class func getDetails() ->String {
return "bar"
}
}
var arr = [Foo.self, Bar.self]
func test1 () {
var x = Foo.self
println(x.getDetails()) //prints foo
if let y = arr[0] as? Foo.Type {
println(y.getDetails()) //doesn't execute
}
if let z = arr[0] as? BaseClass.Type {
println(z.getDetails()) //doesn't execute
}
if let t = arr[0] as? BaseClass {
println(t.dynamicType.getDetails()) //doesn't execute
}
// lets crash
var w = arr[0] as! Foo
//Could not cast value of type 'Test.Foo' (0x1085f17f0) to 'Test.Foo' (0x1085f1830).
}
我特别困惑
无法转换类型' Test.Foo' (0x1085f17f0)到' Test.Foo' (0x1085f1830)
错误。如何通过向下转换到BaseClass
来引用数组中的类,以便我可以使用其getDetails
函数
答案 0 :(得分:1)
var arr = [Foo.self, Bar.self]
println(arr.count)
println(arr)
将打印2然后崩溃,但这样可以正常工作:
var arr: [BaseClass.Type] = [Foo.self, Bar.self]
println(arr.count)
println(arr)
除了稍后在代码中收到有关as? BaseClass.Type
测试总是成功(因此,不需要)的警告,并且as? BaseClass
测试总是失败(预期,因为数组的内容不是类的实例,而是类型)。
在{{3>}指南的定义类型转换的类层次结构部分中,我们找到了
Swift的类型检查器能够推断出Movie和Song有一个 MediaItem的常见超类,因此它推断出一种[MediaItem] 对于库数组:
let library = [
Movie(name: "Casablanca", director: "Michael Curtiz"),
Song(name: "Blue Suede Shoes", artist: "Elvis Presley"),
Movie(name: "Citizen Kane", director: "Orson Welles"),
Song(name: "The One And Only", artist: "Chesney Hawkes"),
Song(name: "Never Gonna Give You Up", artist: "Rick Astley")
]
// the type of "library" is inferred to be [MediaItem]
看起来你正在做类似的事情,所以人们会期望它能够发挥作用,但你不会 - 你正在存储类的类型,而不是它们的实例。 / p>
答案 1 :(得分:0)
所以Foo.self等同于目标c的[Object class]。 所以在
var arr = [Foo.self, Bar.self]
你基本上是在创建一个类类型数组(不是基类BaseClass的对象--Foo,Bar)
开启
var w = arr[0] as! Foo
您正在尝试将Class类型强制转换为该类类型的对象。此操作是不可能的,但您尝试使用它来强制执行!这将导致你的崩溃。
要了解其他向下转换无效的原因,请在playgroung中尝试:
println("\(_stdlib_getDemangledTypeName(Foo.self))")
println("\(_stdlib_getDemangledTypeName(Foo.Type))")
答案 2 :(得分:0)
我怀疑你使用的是旧版Swift。我发现在6.3中,你需要为arr
提供一个类型(我怀疑6.2正在解决这个问题,这可能是你问题的根源):
let arr: [BaseClass.Type] = [Foo.self, Bar.self]
让我们来看看其余的事情:
let x = Foo.self
println("x:" + x.getDetails()) //prints foo
是的;应该是预期的。
if let y = arr[0] as? Foo.Type {
println("y" + y.getDetails()) //doesn't execute
}
我发现它确实在6.3中执行。也就是说,这是不必要的,因为BaseClass
包含getDetails
方法。以下也适用:
let y2 = arr[0]
println("y2:" + y2.getDetails())
下一步:
if let z = arr[0] as? BaseClass.Type {
println("z:" + z.getDetails()) //doesn't execute
}
我发现它确实会执行,正如您所期望的那样,尽管这是不必要的。
if let t = arr[0] as? BaseClass {
println(t.dynamicType.getDetails()) //doesn't execute
}
这不起作用(你得到警告)。一个类不是实例。
let w = arr[0] as! Foo
这会像预期的那样崩溃,因为一个类不是一个实例。
因此,如果您正确执行此操作,则不需要进行类型转换。你可以拥有一组类,并调用它们。也就是说,你应该总是在Swift中认真思考你是否真的需要一堂课。通常,更好的解决方案是结构和协议。