在Swift中,可选类型可以转换为类类型的变量。

4
我在Google和SO上寻找类似的问题,但没有找到直接相关的。可能有两个相似的C#问题,但我不懂这种语言,所以我无法正确理解这些问题 (如何将对象强制转换为Type类描述的类型?,以及将变量强制转换为由另一个Type变量表示的类型?)。
我正在尝试在SpriteKit中的中编写通用的场景切换函数。我创建了一个枚举作为参数。错误出现在尝试将变量可选转换为我期望的通用类型时。
只是想澄清一下,我确信有很多原因说明这不是一个好主意。我可以想到其他处理场景更改的方法,比如为每个场景更改编写单独的方法。我只是出于技术角度好奇为什么会出现我无法理解的错误。
相关代码如下:
在中:
func genericSceneChangeWithType(sceneChangeType: SceneChangeType) {
    let expectedType = sceneChangeType.oldSceneType
    guard let oldScene = self.currentScene as? expectedType else { return }
    ...
}

enum SceneChangeType {
    case TitleSceneToGameScene
    var oldSceneType: SKScene.Type {
        switch self {
        case .TitleSceneToGameScene:
            return TitleScene.self
        }
    }
    ...
}

为了澄清,TitleSceneSKScene的自定义子类,而self.currentScene的类型为SKScene?

在这行代码中,

guard let oldScene = self.currentScene as? expectedType else { return }

我遇到了错误,

'expectedType' is not a type

我是否对事情有误解?我认为您可以使用类似的语法从函数返回通用类型(例如Swift:如何从函数中返回类类型)。问题是因为它是一个属性吗?这不可能吗,或者在预期类型直到运行时才知道的情况下,还有其他检查类型的方法吗?
再强调一遍,我不是在询问更改场景的更好方法,而且我不确定是否有任何例子是绝对必要的。但是了解为什么这样做不起作用可能会帮助我或其他人更好地理解该语言的工作原理。
谢谢。
2个回答

2
您的想法是正确的,只是您将运行时与编译时信息混淆了。当您使用 as 进行强制转换时,您需要在编译时提供一个类型。这可以是显式的类型,如 String,也可以是泛型参数(因为泛型是编译时特性)。然而,您不能传递包含类型的变量,如 expectedType
相反,您可以进行检查:
if self.currentScene.dynamicType == expectedType

然而,由于它没有强制转换currentScene,因此您无法调用任何特定于expectedType的方法。如果currentScene子类,那么它也不起作用,而您可能希望它起作用。问题在于,在运行时传递类型,而需要在编译时了解类型以调用方法或转换。

因此,您需要的是Swift语言功能,它们似乎很有用,但可以在编译时工作,我可以想到两个:

泛型,如下所示:

func genericSceneChange<OldType: SKScene, NewType: SKScene>() {
    ...
}

重载,类似于:

func changeTo(scene: OneType) {
    //do something
}

func changeTo(scene: OtherType) {
    //do something else
}

2

虽然泛型是最好的选择,但这个特定的实现在使用原始的sceneChangeType参数名称时有些奇怪。不幸的是,他需要重新设计整个场景切换系统——SceneChangeType本质上是一种运行时的处理方式。 - andyvn22
我同意你的观点,我只是试图帮助他更好地理解为什么会收到“不是类型”的错误。并不一定赞同我的通用函数,只是想向他展示如何将其与他目前的方法集成。 - brightintro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接