Struct mutating func 在同一结构的另一个实例中调用函数
Struct mutating func calling a func in another instance of the same struct
我今天在 swift 学习结构和 类,并决定尝试使用我新发现的知识来简化我之前构建的战斗计算器。现在我明白了,在 func 中调用的属性本质上是局部变量,“let”常量更是如此。所以我知道为什么下面的代码有错误,但我想不通的是如何在不使用 nil 合并运算符 (??) 为我的代码增加更多复杂性的情况下实现我的目标。
如有任何建议,我们将不胜感激。
import Foundation
import Glibc
struct Unit {
enum UnitType: String {
case sniper
case shocktrooper
case infantry
case support
}
let name: String
let type: UnitType
var hitPoints: Int
let attackStrength: Int
//attack another unit
mutating func attack(target: Unit) {
print("\(self.name) is attacking \(target.name)...")
if self.attackStrength > target.attackStrength {
print("\(self.name) hit \(target.name) for
\(self.attackStrength) points of damage!")
target.hit(target, self.attackStrength) /*error: cannont use
muatating member on imutable value: 'target is a 'let' constant */
} else {
self.repelled(by: target.attackStrength)
}
}
//take damage from defender
mutating func repelled(by damage: Int) {
self.hitPoints -= damage
print("\(name) was repelled and took \(damage) points of damage!")
}
//take damage from attack
mutating func hit(for damage: Int) {
self.hitPoints -= damage
}
}
//declaring two seperate units
var player1 = Unit(name: "Player 1", type: .sniper, hitPoints: 10,
attackStrength: 3)
var player2 = Unit(name: "Player 2", type: .shocktrooper, hitPoints: 15,
attackStrength: 2)
func score() {
print("The current hitpoints are: \(player1.name): \(player1.hitPoints)
& \(player2.name): \(player2.hitPoints)")
}
player1.attack(target: player2)
score()
你只需要使用 inout
关键字就可以改变你的 player2:
struct Unit {
enum Kind: String {
case sniper, shocktrooper, infantry, support
}
let name: String
let kind: Kind
var hitPoints: Int
let attackStrength: Int
mutating func attack(target: inout Unit) {
print("\(name) is attacking \(target.name)...")
if attackStrength > target.attackStrength {
print("\(name) hit \(target.name) for \(attackStrength) points of damage!")
target.hit(for: attackStrength)
} else {
repelled(by: target.attackStrength)
}
}
mutating func repelled(by damage: Int) {
hitPoints -= damage
print("\(name) was repelled and took \(damage) points of damage!")
}
mutating func hit(for damage: Int) {
hitPoints -= damage
}
}
游乐场测试
var player1 = Unit(name: "Player 1", kind: .sniper, hitPoints: 10, attackStrength: 3)
var player2 = Unit(name: "Player 2", kind: .shocktrooper, hitPoints: 15, attackStrength: 2)
func score() {
print("The current hitpoints are: \(player1.name): \(player1.hitPoints) & \(player2.name): \(player2.hitPoints)")
}
player1.attack(target: &player2)
score()
这将打印
Player 1 is attacking Player 2...
Player 1 hit Player 2 for 3 points of damage!
The current hitpoints are: Player 1: 10 & Player 2: 12
另一个选择是使用 class 而不是结构。您需要为您的 class 提供自定义初始化器并从您的方法中删除 mutating 关键字
class Unit {
enum Kind: String {
case sniper, shocktrooper, infantry, support
}
let name: String
let kind: Kind
var hitPoints: Int
let attackStrength: Int
init(name: String, kind: Kind, hitPoints: Int, attackStrength: Int){
self.name = name
self.kind = kind
self.hitPoints = hitPoints
self.attackStrength = attackStrength
}
func attack(target: Unit) {
print("\(name) is attacking \(target.name)...")
if attackStrength > target.attackStrength {
print("\(name) hit \(target.name) for \(attackStrength) points of damage!")
target.hit(for: attackStrength)
} else {
repelled(by: target.attackStrength)
}
}
func repelled(by damage: Int) {
hitPoints -= damage
print("\(name) was repelled and took \(damage) points of damage!")
}
func hit(for damage: Int) {
hitPoints -= damage
}
}
let player1 = Unit(name: "Player 1", kind: .sniper, hitPoints: 10, attackStrength: 3)
let player2 = Unit(name: "Player 2", kind: .shocktrooper, hitPoints: 15, attackStrength: 2)
func score() {
print("The current hitpoints are: \(player1.name): \(player1.hitPoints) & \(player2.name): \(player2.hitPoints)")
}
player1.attack(target: player2)
score()
我今天在 swift 学习结构和 类,并决定尝试使用我新发现的知识来简化我之前构建的战斗计算器。现在我明白了,在 func 中调用的属性本质上是局部变量,“let”常量更是如此。所以我知道为什么下面的代码有错误,但我想不通的是如何在不使用 nil 合并运算符 (??) 为我的代码增加更多复杂性的情况下实现我的目标。
如有任何建议,我们将不胜感激。
import Foundation
import Glibc
struct Unit {
enum UnitType: String {
case sniper
case shocktrooper
case infantry
case support
}
let name: String
let type: UnitType
var hitPoints: Int
let attackStrength: Int
//attack another unit
mutating func attack(target: Unit) {
print("\(self.name) is attacking \(target.name)...")
if self.attackStrength > target.attackStrength {
print("\(self.name) hit \(target.name) for
\(self.attackStrength) points of damage!")
target.hit(target, self.attackStrength) /*error: cannont use
muatating member on imutable value: 'target is a 'let' constant */
} else {
self.repelled(by: target.attackStrength)
}
}
//take damage from defender
mutating func repelled(by damage: Int) {
self.hitPoints -= damage
print("\(name) was repelled and took \(damage) points of damage!")
}
//take damage from attack
mutating func hit(for damage: Int) {
self.hitPoints -= damage
}
}
//declaring two seperate units
var player1 = Unit(name: "Player 1", type: .sniper, hitPoints: 10,
attackStrength: 3)
var player2 = Unit(name: "Player 2", type: .shocktrooper, hitPoints: 15,
attackStrength: 2)
func score() {
print("The current hitpoints are: \(player1.name): \(player1.hitPoints)
& \(player2.name): \(player2.hitPoints)")
}
player1.attack(target: player2)
score()
你只需要使用 inout
关键字就可以改变你的 player2:
struct Unit {
enum Kind: String {
case sniper, shocktrooper, infantry, support
}
let name: String
let kind: Kind
var hitPoints: Int
let attackStrength: Int
mutating func attack(target: inout Unit) {
print("\(name) is attacking \(target.name)...")
if attackStrength > target.attackStrength {
print("\(name) hit \(target.name) for \(attackStrength) points of damage!")
target.hit(for: attackStrength)
} else {
repelled(by: target.attackStrength)
}
}
mutating func repelled(by damage: Int) {
hitPoints -= damage
print("\(name) was repelled and took \(damage) points of damage!")
}
mutating func hit(for damage: Int) {
hitPoints -= damage
}
}
游乐场测试
var player1 = Unit(name: "Player 1", kind: .sniper, hitPoints: 10, attackStrength: 3)
var player2 = Unit(name: "Player 2", kind: .shocktrooper, hitPoints: 15, attackStrength: 2)
func score() {
print("The current hitpoints are: \(player1.name): \(player1.hitPoints) & \(player2.name): \(player2.hitPoints)")
}
player1.attack(target: &player2)
score()
这将打印
Player 1 is attacking Player 2...
Player 1 hit Player 2 for 3 points of damage!
The current hitpoints are: Player 1: 10 & Player 2: 12
另一个选择是使用 class 而不是结构。您需要为您的 class 提供自定义初始化器并从您的方法中删除 mutating 关键字
class Unit {
enum Kind: String {
case sniper, shocktrooper, infantry, support
}
let name: String
let kind: Kind
var hitPoints: Int
let attackStrength: Int
init(name: String, kind: Kind, hitPoints: Int, attackStrength: Int){
self.name = name
self.kind = kind
self.hitPoints = hitPoints
self.attackStrength = attackStrength
}
func attack(target: Unit) {
print("\(name) is attacking \(target.name)...")
if attackStrength > target.attackStrength {
print("\(name) hit \(target.name) for \(attackStrength) points of damage!")
target.hit(for: attackStrength)
} else {
repelled(by: target.attackStrength)
}
}
func repelled(by damage: Int) {
hitPoints -= damage
print("\(name) was repelled and took \(damage) points of damage!")
}
func hit(for damage: Int) {
hitPoints -= damage
}
}
let player1 = Unit(name: "Player 1", kind: .sniper, hitPoints: 10, attackStrength: 3)
let player2 = Unit(name: "Player 2", kind: .shocktrooper, hitPoints: 15, attackStrength: 2)
func score() {
print("The current hitpoints are: \(player1.name): \(player1.hitPoints) & \(player2.name): \(player2.hitPoints)")
}
player1.attack(target: player2)
score()