我可以使用 swift 使 self.entity 成为组件中某些功能的非可选功能吗?
Can I make self.entity a non optional for certian functions in a GKComponent using swift?
我正在使用 GameplayKit 实体组件系统开发游戏。
我有多个GKComponent。大多数实例函数要求 self.entity 不是 nil,但它是可选的,因为组件可能在附加到实体之前被初始化。
如果我 "do things properly",我知道我应该使用 guard
(或 if)来检查 self.entity 是否为零,对于我需要它的每个函数。这为每个功能添加了一大块额外代码,此外,功能可能需要实体具有特定组件才能运行。
问题陈述:
对于 GKComponent 中的一些函数,我想指定该函数需要 self.entity 不是 nil,并且有一些特定的组件,而不需要一些 guard 或 if 语句来增加我的代码。
我尝试过的事情:
我尝试创建 GKComponent 的扩展。
该扩展包含一个函数,如果实体为 nil 则抛出错误,return如果它不是 nil 则为真。
import Foundation
import GameplayKit
extension GKComponent {
enum ComponentExtensionError: Error {
case hasNoEntity
}
func requiresEntity() throws -> Bool {
if (self.entity != nil) {
return true
} else {
throw ComponentExtensionError.hasNoEntity
}
}
}
GK组件函数:
func setTileWalls () {
try? self.requiresEntity()
# Some stuff
}
这可以编译,但没有解决我的问题,因为我仍然必须以 self.entity?.somefunc()
的身份访问实体。
我想现在我知道 self.entity 不是零,我可以继续将它设置为展开...
func setTileWalls () {
try? self.requiresEntity()
self.entity = self.entity!
# Some stuff
}
但是,唉,你不能设置self.entity。
我认为我可以改为将扩展修改为 return 实体,然后执行类似...
func stTileWalls () {
guard let entity = self.requiresEntity() else { throw }
}
但随后我需要修改每个函数代码以使用 entity
而不是 self.entity
。我觉得这不是最佳解决方案,但也许是可以接受的。
我理想的解决方案是能够调用一个函数来检查 self 是否有一个实体和一些组件,使它们对于范围来说是非可选的,如果有任何是 nil 则抛出错误。
为什么?我对实体和任何组件总是可选的感到沮丧(当我知道它不应该时)。如果我理解正确的话,"doing things properly" 要求我守卫和投掷(或者 return 可能?)。从语法上讲,我觉得它看起来很丑陋,而且我觉得在使用 Swift.
以优雅的方式修复它方面我遗漏了一些东西
如果您想要一个安全的解决方案,需要比展开可选代码更少的样板代码,则没有简单的解决方案来解决这个问题。
抛出错误而不是返回 nil 绝对是个坏主意,因为处理错误需要的样板代码比安全地解包可选代码还要多。
您不能覆盖现有的变量类型,因此您也不能使 GKComponent.entity
成为非可选的。
使用 guard 语句进行可选绑定,这样您就可以最小化解包值的样板代码。
我正在使用 GameplayKit 实体组件系统开发游戏。
我有多个GKComponent。大多数实例函数要求 self.entity 不是 nil,但它是可选的,因为组件可能在附加到实体之前被初始化。
如果我 "do things properly",我知道我应该使用 guard
(或 if)来检查 self.entity 是否为零,对于我需要它的每个函数。这为每个功能添加了一大块额外代码,此外,功能可能需要实体具有特定组件才能运行。
问题陈述:
对于 GKComponent 中的一些函数,我想指定该函数需要 self.entity 不是 nil,并且有一些特定的组件,而不需要一些 guard 或 if 语句来增加我的代码。
我尝试过的事情:
我尝试创建 GKComponent 的扩展。 该扩展包含一个函数,如果实体为 nil 则抛出错误,return如果它不是 nil 则为真。
import Foundation
import GameplayKit
extension GKComponent {
enum ComponentExtensionError: Error {
case hasNoEntity
}
func requiresEntity() throws -> Bool {
if (self.entity != nil) {
return true
} else {
throw ComponentExtensionError.hasNoEntity
}
}
}
GK组件函数:
func setTileWalls () {
try? self.requiresEntity()
# Some stuff
}
这可以编译,但没有解决我的问题,因为我仍然必须以 self.entity?.somefunc()
的身份访问实体。
我想现在我知道 self.entity 不是零,我可以继续将它设置为展开...
func setTileWalls () {
try? self.requiresEntity()
self.entity = self.entity!
# Some stuff
}
但是,唉,你不能设置self.entity。
我认为我可以改为将扩展修改为 return 实体,然后执行类似...
func stTileWalls () {
guard let entity = self.requiresEntity() else { throw }
}
但随后我需要修改每个函数代码以使用 entity
而不是 self.entity
。我觉得这不是最佳解决方案,但也许是可以接受的。
我理想的解决方案是能够调用一个函数来检查 self 是否有一个实体和一些组件,使它们对于范围来说是非可选的,如果有任何是 nil 则抛出错误。
为什么?我对实体和任何组件总是可选的感到沮丧(当我知道它不应该时)。如果我理解正确的话,"doing things properly" 要求我守卫和投掷(或者 return 可能?)。从语法上讲,我觉得它看起来很丑陋,而且我觉得在使用 Swift.
以优雅的方式修复它方面我遗漏了一些东西如果您想要一个安全的解决方案,需要比展开可选代码更少的样板代码,则没有简单的解决方案来解决这个问题。 抛出错误而不是返回 nil 绝对是个坏主意,因为处理错误需要的样板代码比安全地解包可选代码还要多。
您不能覆盖现有的变量类型,因此您也不能使 GKComponent.entity
成为非可选的。
使用 guard 语句进行可选绑定,这样您就可以最小化解包值的样板代码。