Swift 2:为什么用‘copy()’得到新的对象后还要用‘as!’?

Swift 2: Why is it necessary to apply ‘as!’ after getting new object by ‘copy()’?

我使用 copy() 方法创建了新的 SKEmitterNode 对象。之后我尝试写 emitter.position 但 Xcode 说“对成员‘位置’的引用不明确”。但是,当我使用类型转换 «as! «copy()» 之后的 SKEmitterNode»,一切正常。请你解释一下,为什么我需要使用 «as!»在这种情况下?我无法理解这一点,因为当我在调试器中检查 «emit» 变量的值类型时,我可以看到它已经具有 SKEmitterNode 类型,即使没有使用 «as!在 «copy()» 之后的 SKEmitterNode»。

class GameScene: SKScene, SKPhysicsContactDelegate {

    let bangEmitter : SKEmitterNode = SKEmitterNode(fileNamed: "MyParticle")!

    func makeBang(position: CGPoint) {

        // this method causes an error in second line
        // but, emit is already have type SKEmitterNode, as debugger says
        var emit = bangEmitter.copy()
        emit.position = position

        // this works ok
        var emit = bangEmitter.copy() as! SKEmitterNode
        emit.position = position

    }

}

使用 as! 表示检查可能失败。

Swift 1.2 separates the notions of guaranteed conversion and forced conversion into two distinct operators. Guaranteed conversion is still performed with the as operator, but forced conversion now uses the as! operator. The ! is meant to indicate that the conversion may fail. This way, you know at a glance which conversions may cause the program to crash.

参考:https://developer.apple.com/swift/blog/?id=23

查找函数 copy() 的定义,您会发现它总是 returns Any,因此您总是需要将它转换为您正在寻找的对象。

因为 copy() 是由 NSObject 定义的方法,意味着被 subclasses 覆盖以提供他们自己的实现。 NSObject 本身不支持它,如果你在它上面调用 copy() 会抛出异常。

因为它是为 subclassing 设计的,所以无法判断将返回的对象的 class 是什么。在 Objective-C 中,它 returns 一个 id;在 Swift 中,这变为 AnyObject。既然你,程序员,知道你正在复制什么样的对象,你可以使用 as! SomeClass 告诉编译器副本是什么类型的对象。

这也说明了ObjectiveC和Swift的区别。 Objective-C 是动态的。在Objective-C中,每次发送消息,运行时间都会检查对象是否响应消息。这发生在 运行 时间 。在 Swift 中,您 调用一个方法 ,这发生在 编译时 。编译器必须知道对象的类型才能调用正确的函数/方法。

这解释了为什么您在调试器中将 emit 作为 SKEmitterNode - 这是 运行 时间。编译器在编译时不知道。