了解如何将 类 变成 Swift 中的协议
Understanding how to turn Classes into Protocols in Swift
我的代码工作正常!但是,我对抽象 classes 和协议研究得越多,我就越开始认为我代码背后的 "logic" 是完全错误的。让我更详细地解释一下:
我有一个名为 SpaceObject
的 class
,它是对继承的 classes 的一种抽象。它基本上具有一些属性和物理特性。 不应初始化此 class,因为它的工作方式与 "blueprint"
相同
class SpaceObject: SKSpriteNode {
final var atmosphere: SKSpriteNode
init(style: SKTexture, initialVelocity: CGVector) {
atmosphere = SKSpriteNode(texture: SKTexture(imageNamed: "atmosphere"), size: CGSize(width: 100, height: 100))
atmosphere.zPosition = 2
// calls the initializer
super.init(texture: style, color: .clear, size: style.size())
physicsBody = SKPhysicsBody(circleOfRadius: style.size().width)
physicsBody?.velocity = initialVelocity
physicsBody?.affectedByGravity = false
...
addChild(atmosphere)
}
final func cleanAtmosphere() {
atmosphere.run( ... )
}
}
我这里有子classes。他们只是 "fill" SpaceObject class 但使用它的物理学和一些其他功能(例如 cleanAtmosphere()
)。
final class World: SpaceObject {
enum WorldType: String {
case Venus, Earth, ...
}
var type: WorldType
var gravity: CGFloat
init(world: WorldType, initialVelocity: CGVector, gravity: CGFloat) {
self.type = world
self.gravity = gravity
// calls the initializer
super.init(style: SKTexture(imageNamed: "world_\(self.type)"), initialVelocity: initialVelocity)
}
func touchedOccurred() {
...
cleanAtmosphere()
...
}
}
final class Star: SpaceObject {
enum StarType: String {
case Sirius, Polaris, ...
}
var type: StarType
init(star: StarType, initialVelocity: CGVector) {
self.type = star
// calls the initializer
super.init(style: SKTexture(imageNamed: "star_\(self.type)"), initialVelocity: initialVelocity)
}
func explode() {
...
}
}
我创建一个对象只是:
let newWorld = World(world: .Venus, initialVelocity: someVector, gravity: CGFloat(8.87))
而且我确定它会有大气层 SKSpriteNode
和一些对每个 SpaceObject 都有效的物理规则。
但是...我不确定我做的是否正确,我读到协议需要处理这样的情况,但我仍然不知道如何处理。有什么提示吗?
您可以使用继承来做您想做的事,但协议也是一种选择。协议的优点是 Swift 结构可以使用它们并且 class 可以符合多个协议但只能继承一个 class.
你提到了物理规则。如果你想使用一个协议,你可以为规则创建一个协议,并包含 classes/structs 必须实现以符合该协议的功能。该函数将创建规则。
protocol PhysicsRules {
// Add any arguments the function takes.
func yourPhysicsRule()
// Add any other physics functions you want here.
}
那你的World和Starclasses就符合协议,实现了yourPhysicsRule
功能
final class World: SpaceObject, PhysicsRules {
func yourPhysicsRule() {
// Add the code to create the rule here.
}
}
您可以为协议和函数想出更好的名称,但这让您了解了要转换到协议必须执行的操作。
通过网络搜索 Swift protocols
可以找到很多面向协议编程的教程,包括以下内容:
A Beginner’s Guide to Protocols and Protocol Extensions in Swift
Protocol-Oriented Programming Tutorial in Swift 5.1: Getting Started
我的代码工作正常!但是,我对抽象 classes 和协议研究得越多,我就越开始认为我代码背后的 "logic" 是完全错误的。让我更详细地解释一下:
我有一个名为 SpaceObject
的 class
,它是对继承的 classes 的一种抽象。它基本上具有一些属性和物理特性。 不应初始化此 class,因为它的工作方式与 "blueprint"
class SpaceObject: SKSpriteNode {
final var atmosphere: SKSpriteNode
init(style: SKTexture, initialVelocity: CGVector) {
atmosphere = SKSpriteNode(texture: SKTexture(imageNamed: "atmosphere"), size: CGSize(width: 100, height: 100))
atmosphere.zPosition = 2
// calls the initializer
super.init(texture: style, color: .clear, size: style.size())
physicsBody = SKPhysicsBody(circleOfRadius: style.size().width)
physicsBody?.velocity = initialVelocity
physicsBody?.affectedByGravity = false
...
addChild(atmosphere)
}
final func cleanAtmosphere() {
atmosphere.run( ... )
}
}
我这里有子classes。他们只是 "fill" SpaceObject class 但使用它的物理学和一些其他功能(例如 cleanAtmosphere()
)。
final class World: SpaceObject {
enum WorldType: String {
case Venus, Earth, ...
}
var type: WorldType
var gravity: CGFloat
init(world: WorldType, initialVelocity: CGVector, gravity: CGFloat) {
self.type = world
self.gravity = gravity
// calls the initializer
super.init(style: SKTexture(imageNamed: "world_\(self.type)"), initialVelocity: initialVelocity)
}
func touchedOccurred() {
...
cleanAtmosphere()
...
}
}
final class Star: SpaceObject {
enum StarType: String {
case Sirius, Polaris, ...
}
var type: StarType
init(star: StarType, initialVelocity: CGVector) {
self.type = star
// calls the initializer
super.init(style: SKTexture(imageNamed: "star_\(self.type)"), initialVelocity: initialVelocity)
}
func explode() {
...
}
}
我创建一个对象只是:
let newWorld = World(world: .Venus, initialVelocity: someVector, gravity: CGFloat(8.87))
而且我确定它会有大气层 SKSpriteNode
和一些对每个 SpaceObject 都有效的物理规则。
但是...我不确定我做的是否正确,我读到协议需要处理这样的情况,但我仍然不知道如何处理。有什么提示吗?
您可以使用继承来做您想做的事,但协议也是一种选择。协议的优点是 Swift 结构可以使用它们并且 class 可以符合多个协议但只能继承一个 class.
你提到了物理规则。如果你想使用一个协议,你可以为规则创建一个协议,并包含 classes/structs 必须实现以符合该协议的功能。该函数将创建规则。
protocol PhysicsRules {
// Add any arguments the function takes.
func yourPhysicsRule()
// Add any other physics functions you want here.
}
那你的World和Starclasses就符合协议,实现了yourPhysicsRule
功能
final class World: SpaceObject, PhysicsRules {
func yourPhysicsRule() {
// Add the code to create the rule here.
}
}
您可以为协议和函数想出更好的名称,但这让您了解了要转换到协议必须执行的操作。
通过网络搜索 Swift protocols
可以找到很多面向协议编程的教程,包括以下内容:
A Beginner’s Guide to Protocols and Protocol Extensions in Swift
Protocol-Oriented Programming Tutorial in Swift 5.1: Getting Started