如何使用静态方法更改 属性 值?
How to change property value with static method?
在这个简单的游戏中有一个 class 战士,其目的是让两个战士战斗。血量低于0的一方输掉比赛。
为了战斗,有一个静态方法战斗 (..) 迭代直到一个战士赢得比赛,由另一个非静态方法攻击支持 (..)
object Fighter 的生命值应该随着两个对象在游戏中使用 fight(...) 和 attack (...) 方法进行战斗而改变。问题是它总是打印相同的 Fighter 生命值,而且游戏永远不会结束。我看不出问题出在哪里
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let david = Fighter(name: "David", health: 100, damage: 30, defense: 10, initiative: 80)
let goliath = Fighter(name: "Goliath", health: 300, damage: 60, defense: 14, initiative: 90)
let myFight1 = Fighter.fight(fighter1: david, fighter2: goliath) // always executing same Fighters
print(myFight1)
}
}
import Foundation
struct Fighter {
var name: String
var health: Double
var damage: Int
var defense: Int
var initiative: Int
init (name: String, health: Double, damage: Int, defense: Int, initiative: Int) {
self.name = name
self.health = health
self.damage = damage
self.defense = defense
self.initiative = initiative
}
init (name: String, health: Double, damage: Int, defense: Int) {
self.name = name
self.health = health
self.damage = damage
self.defense = defense
self.initiative = 0
}
static func fight(fighter1: Fighter, fighter2: Fighter) -> Fighter {
let f1 = fighter1
let f2 = fighter2
if f1.health == f2.health {
return f1
}
if f2.initiative > f1.initiative {
f2.attack(f: f1)
}
var i = 0
while f1.health > 0 {
i += 1
print("--> i: \(i)")
f1.attack(f: f2 )
if f2.health <= 0 {
return f1
}
f2.attack(f: f1)
}
return f2
}
func attack(f: Fighter) -> Void {
var g = f
g.health = g.health - Double(g.damage * (1 - g.defense / 100))
print(g)
}
}
您正在为 Fighter
使用 struct
,它是 Swift 中的 值 类型。
The most basic distinguishing feature of a value type is that copying — the effect of assignment, initialization, and argument passing —
creates an independent instance with its own unique copy of its data
解决方案:将Fighter
更改为class
即可。
打印语句的输出:(第二次打印语句改为print(g.name, g.health)
)
David 70.0
--> i: 1
Goliath 240.0
David 40.0
--> i: 2
Goliath 180.0
David 10.0
--> i: 3
Goliath 120.0
David -20.0
每次调用方法func attack(f: Fighter) -> Void
后,被攻击的Fighter
的属性都没有更新。所以 while
循环不会在任何时候中断。
请替换下面的代码。
static func fight(fighter1: Fighter, fighter2: Fighter) -> Fighter {
var f1 = fighter1
var f2 = fighter2
if f1.health == f2.health {
return f1
}
if f2.initiative > f1.initiative {
f1 = f2.attack(f: f1)
}
var i = 0
while f1.health > 0 {
i += 1
print("--> i: \(i)")
f2 = f1.attack(f: f2 )
if f2.health <= 0 {
return f1
}
f1 = f2.attack(f: f1)
}
return f2
}
func attack( f: Fighter) -> Fighter {
var g = f
g.health = g.health - Double(g.damage * (1 - g.defense / 100))
print(g)
return g
}
当你说...
var g = f
...您实际上是在创建该对象的副本,而不是引用。因此,当您更改 'health' 属性 时,您会在副本中更改它。
有 2 个简单的解决方案:
1) 将结构更改为 class,因为 classes 被引用,不像结构,它只是复制。
2) 用修改后的副本替换原始对象 (g)
正如 Rakesha 指出的那样,结构是值类型,因此您的 attack
代码实际上不会修改任何内容:
func attack(f: Fighter) -> Void {
var g = f // Make a mutable copy of `f` called `g`
g.health = g.health - Double(g.damage * (1 - g.defense / 100)) // Modify g
print(g) // Print g
// Throw g away
}
(旁注:我认为 g.damage
在这里是不正确的;我认为您的意思可能是 self.damage
。)
实际上没有任何修改 f
。有几种方法可以解决这个问题。一种是使用 类,它引入了微妙的可变状态。我不认为我会在这里这样做。 "subtle mutable state" 我的意思是您希望 attack
修改 f
,但签名中没有任何内容表明它这样做,因此调用者可能会感到惊讶。
相反,您可以通过多种方式实现这一点,从而使您的突变在结构上显式化。您可以使 attack
显式修改 f
:
func attack(f: inout Fighter) {
f.health = f.health - Double(damage * (1 - f.defense / 100))
}
或者你也可以在被别人攻击的时候反过来修改自己:
mutating func attackedBy(f: Fighter) {
health = health - Double(f.damage * (1 - defense / 100)
}
在这个简单的游戏中有一个 class 战士,其目的是让两个战士战斗。血量低于0的一方输掉比赛。
为了战斗,有一个静态方法战斗 (..) 迭代直到一个战士赢得比赛,由另一个非静态方法攻击支持 (..)
object Fighter 的生命值应该随着两个对象在游戏中使用 fight(...) 和 attack (...) 方法进行战斗而改变。问题是它总是打印相同的 Fighter 生命值,而且游戏永远不会结束。我看不出问题出在哪里
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let david = Fighter(name: "David", health: 100, damage: 30, defense: 10, initiative: 80)
let goliath = Fighter(name: "Goliath", health: 300, damage: 60, defense: 14, initiative: 90)
let myFight1 = Fighter.fight(fighter1: david, fighter2: goliath) // always executing same Fighters
print(myFight1)
}
}
import Foundation
struct Fighter {
var name: String
var health: Double
var damage: Int
var defense: Int
var initiative: Int
init (name: String, health: Double, damage: Int, defense: Int, initiative: Int) {
self.name = name
self.health = health
self.damage = damage
self.defense = defense
self.initiative = initiative
}
init (name: String, health: Double, damage: Int, defense: Int) {
self.name = name
self.health = health
self.damage = damage
self.defense = defense
self.initiative = 0
}
static func fight(fighter1: Fighter, fighter2: Fighter) -> Fighter {
let f1 = fighter1
let f2 = fighter2
if f1.health == f2.health {
return f1
}
if f2.initiative > f1.initiative {
f2.attack(f: f1)
}
var i = 0
while f1.health > 0 {
i += 1
print("--> i: \(i)")
f1.attack(f: f2 )
if f2.health <= 0 {
return f1
}
f2.attack(f: f1)
}
return f2
}
func attack(f: Fighter) -> Void {
var g = f
g.health = g.health - Double(g.damage * (1 - g.defense / 100))
print(g)
}
}
您正在为 Fighter
使用 struct
,它是 Swift 中的 值 类型。
The most basic distinguishing feature of a value type is that copying — the effect of assignment, initialization, and argument passing — creates an independent instance with its own unique copy of its data
解决方案:将Fighter
更改为class
即可。
打印语句的输出:(第二次打印语句改为print(g.name, g.health)
)
David 70.0
--> i: 1
Goliath 240.0
David 40.0
--> i: 2
Goliath 180.0
David 10.0
--> i: 3
Goliath 120.0
David -20.0
每次调用方法func attack(f: Fighter) -> Void
后,被攻击的Fighter
的属性都没有更新。所以 while
循环不会在任何时候中断。
请替换下面的代码。
static func fight(fighter1: Fighter, fighter2: Fighter) -> Fighter {
var f1 = fighter1
var f2 = fighter2
if f1.health == f2.health {
return f1
}
if f2.initiative > f1.initiative {
f1 = f2.attack(f: f1)
}
var i = 0
while f1.health > 0 {
i += 1
print("--> i: \(i)")
f2 = f1.attack(f: f2 )
if f2.health <= 0 {
return f1
}
f1 = f2.attack(f: f1)
}
return f2
}
func attack( f: Fighter) -> Fighter {
var g = f
g.health = g.health - Double(g.damage * (1 - g.defense / 100))
print(g)
return g
}
当你说...
var g = f
...您实际上是在创建该对象的副本,而不是引用。因此,当您更改 'health' 属性 时,您会在副本中更改它。 有 2 个简单的解决方案:
1) 将结构更改为 class,因为 classes 被引用,不像结构,它只是复制。
2) 用修改后的副本替换原始对象 (g)
正如 Rakesha 指出的那样,结构是值类型,因此您的 attack
代码实际上不会修改任何内容:
func attack(f: Fighter) -> Void {
var g = f // Make a mutable copy of `f` called `g`
g.health = g.health - Double(g.damage * (1 - g.defense / 100)) // Modify g
print(g) // Print g
// Throw g away
}
(旁注:我认为 g.damage
在这里是不正确的;我认为您的意思可能是 self.damage
。)
实际上没有任何修改 f
。有几种方法可以解决这个问题。一种是使用 类,它引入了微妙的可变状态。我不认为我会在这里这样做。 "subtle mutable state" 我的意思是您希望 attack
修改 f
,但签名中没有任何内容表明它这样做,因此调用者可能会感到惊讶。
相反,您可以通过多种方式实现这一点,从而使您的突变在结构上显式化。您可以使 attack
显式修改 f
:
func attack(f: inout Fighter) {
f.health = f.health - Double(damage * (1 - f.defense / 100))
}
或者你也可以在被别人攻击的时候反过来修改自己:
mutating func attackedBy(f: Fighter) {
health = health - Double(f.damage * (1 - defense / 100)
}