Swift 向下转型失败
Swift downcasting fails
我遇到了非常奇怪的行为,我真的无法理解它的正反面。我正在尝试将 class 类型存储在数组中并想稍后调用,但它不起作用。这是我的代码
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).
}
我特别疑惑
Could not cast value of type 'Test.Foo' (0x1085f17f0) to 'Test.Foo'
(0x1085f1830)
错误。我如何通过向下转换为 BaseClass
来引用数组中的 classes 我可以使用它的 getDetails
函数
嗯...奇特。这个
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
测试总是失败的警告(预期,因为内容该数组不是 类 的 实例 ,而是它们的 类型 ).
在 The Swift Programming Language 指南的 为类型转换 定义 Class 层次结构部分中,我们发现
Swift’s type checker is able to deduce that Movie and Song have a
common superclass of MediaItem, and so it infers a type of [MediaItem]
for the library array:
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]
看起来你在做类似的事情,所以人们希望它能工作,但你不是 - 你存储的是 类 的类型,而不是它们的实例。
所以 Foo.self 等同于 objective c 中的 [Object class]。
所以在
var arr = [Foo.self, Bar.self]
你基本上是在创建一个 class 类型的数组(不是基础对象 class 基础Class - Foo, Bar)
在
var w = arr[0] as! Foo
您正在尝试将 Class 类型转换为 class 类型的对象。此操作是不可能的,但您尝试使用 !这将导致您的崩溃。
要了解其他向下转换不起作用的原因,请在您的 playgroung 中试试这个:
println("\(_stdlib_getDemangledTypeName(Foo.self))")
println("\(_stdlib_getDemangledTypeName(Foo.Type))")
我怀疑您使用的是 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
}
那是行不通的(并且您会收到警告)。 class 不是实例。
let w = arr[0] as! Foo
这将按预期崩溃,因为 class 不是实例。
因此,如果您正确执行此操作,则不需要进行类型转换。您可以只拥有一个 classes 数组,然后调用它们。也就是说,您应该始终在 Swift 中认真思考您是否真的需要此处的 class。通常更好的解决方案是结构和协议。
我遇到了非常奇怪的行为,我真的无法理解它的正反面。我正在尝试将 class 类型存储在数组中并想稍后调用,但它不起作用。这是我的代码
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).
}
我特别疑惑
Could not cast value of type 'Test.Foo' (0x1085f17f0) to 'Test.Foo' (0x1085f1830)
错误。我如何通过向下转换为 BaseClass
来引用数组中的 classes 我可以使用它的 getDetails
函数
嗯...奇特。这个
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
测试总是失败的警告(预期,因为内容该数组不是 类 的 实例 ,而是它们的 类型 ).
在 The Swift Programming Language 指南的 为类型转换 定义 Class 层次结构部分中,我们发现
Swift’s type checker is able to deduce that Movie and Song have a common superclass of MediaItem, and so it infers a type of [MediaItem] for the library array:
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]
看起来你在做类似的事情,所以人们希望它能工作,但你不是 - 你存储的是 类 的类型,而不是它们的实例。
所以 Foo.self 等同于 objective c 中的 [Object class]。 所以在
var arr = [Foo.self, Bar.self]
你基本上是在创建一个 class 类型的数组(不是基础对象 class 基础Class - Foo, Bar)
在
var w = arr[0] as! Foo
您正在尝试将 Class 类型转换为 class 类型的对象。此操作是不可能的,但您尝试使用 !这将导致您的崩溃。
要了解其他向下转换不起作用的原因,请在您的 playgroung 中试试这个:
println("\(_stdlib_getDemangledTypeName(Foo.self))")
println("\(_stdlib_getDemangledTypeName(Foo.Type))")
我怀疑您使用的是 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
}
那是行不通的(并且您会收到警告)。 class 不是实例。
let w = arr[0] as! Foo
这将按预期崩溃,因为 class 不是实例。
因此,如果您正确执行此操作,则不需要进行类型转换。您可以只拥有一个 classes 数组,然后调用它们。也就是说,您应该始终在 Swift 中认真思考您是否真的需要此处的 class。通常更好的解决方案是结构和协议。