无法将 SKNode 转换为 SKNode 的子类

Cannot cast SKNode to subclass of SKNode

我从一个函数返回 SKNode,我需要将其转换为自定义 SKNode。我收到错误 Cannot assign value ofSKNodeto typeGroundNode。如果我强制转换,它会编译,但在运行时失败。我错过了什么?

// Custom node class
class GroundNode: SKNode {
        weak var entity: GKEntity!
    }

// Return node function
func returnNode() -> SKNode {
    ...
    return node
}

// Where I am getting the error
func setupNode() {
    var ground: GroundNode
    ground = returnNode() // error here.
    //// ground = returnNode() as! GroundNode fails at runtime.
}

编辑:我从 sks 文件中得到一个 SKNode。我的 returnNode() 只是得到带有名称的 child,然后 returns 它到我的 setupNode() 函数。我需要添加实体 属性,所以我想将返回的 SKNode 转换为 GroundNode 类型。

我看过 this Whosebug post。

这适用于 SKSpiteNode,但显然不适用于 SKNode,这对我来说意义不大。

如果我将 SKNode 从我的 sks 文件转换为 GroundNode,它会在运行时崩溃。

我觉得应该是

func returnNode() -> GroundNode {

根据您的代码:

// Custom node class
class GroundNode: SKNode {
    weak var entity: GKEntity! = GKEntity() // or some custom initialization...
}

// Where I am getting the error
func setupNode() {
   var ground: GroundNode
   ground = returnNode() as? GroundNode
}

发生这种情况是因为 returnNode 输出是一个通用的 SKNode,您必须将您的转换显式转换为子classed GroundNode。

编辑: 好的,通过你的更新我想我已经理解你的问题了,你忘记为你的 GroundNode 设置自定义 class:

第一

returnNode() return 是 SKNode class 的实例。它 可能 也 return 派生 class 的一个实例(例如 GroundNode),但调用站点从函数声明中不知道这一点。您正在尝试将此实例分配给 SKNode 的子 class - GroundNode 的变量,这 在 OOP 中不合适。

参见Dynamic Binding OOP 概念:

In object- oriented programming languages, a variable of a superclass type can contain a subclass instance.

(可能其他人可以更详细地解释这一点,但这就是我的看法)

Type Casting。当您怀疑 class 类型的某个变量可能包含派生 class 的实例时,您可以进行类型转换以证明这一点。

returnNode() returns 是 SKNode 任何派生的实例 class,但调用站点要处理只有派生 class (GroundNode) 的实例,因此应该使用一种类型转换技术。

import GameplayKit
import SpriteKit

// Custom node class
class GroundNode: SKNode {
    var entity: GKEntity = GKEntity()
}

// Return node function
func returnNode() -> SKNode {
    // let's assume that you are correctly getting an instance
    // of GroundNode class here, and return it from the function
    // as of SKNode type
    let returnNode: SKNode = GroundNode()
    return returnNode
}

func setupNode() {
    var groundNode: GroundNode?

    // Type Casting

    // Approach #1
    let someNode = returnNode()
    if someNode is GroundNode {
        groundNode = someNode as! GroundNode
    }

    // Approach #2
    groundNode = returnNode() as? GroundNode

    print("groundNode = \(groundNode)")
}