简体   繁体   English

如何使用静态方法更改属性值?

[英]How to change property value with static method?

In this simple game there is a class Fighter whose purpose is to make two fighters fight. 在这个简单的游戏中,有一类战斗机,其目的是使两名战斗机战斗。 The one who looses health below 0, it looses the game. 生命值低于0的人将失去游戏。

In order to fight there is a static method fight (..) which iterates till one fighter wins the game, supported by another non static method attack (..) 为了进行战斗,需要进行静态方法战斗(..),迭代直到一名战斗机赢得游戏,再由另一种非静态方法攻击(..)支持

object Fighter health should change as two objects fight during the game using the methods fight(...) and attack (...). 对象战斗机的健康状况应该随着两个对象在游戏中使用斗殴(...)和攻击(...)进行战斗而改变。 The problem is it always prints the same Fighter health, and the game never ends. 问题在于它总是打印出相同的Fighter健康状况,并且游戏永远不会结束。 I don´t see where the issue is 我看不出问题出在哪里

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)
    }        
}

You are using a struct for Fighter which is a value type in Swift. 您正在使用Fighterstruct ,这是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 值类型最基本的区别特征是复制-赋值,初始化和参数传递的效果-创建一个具有其数据唯一副本的独立实例

Solution: Change Fighter to a class and you are good to go. 解决方案:将 Fighter更改为class然后就可以开始了。

Output of the print statements: (Second print statement changed to print(g.name, g.health) ) 打印语句的输出 :(第二个打印语句更改为print(g.name, g.health)

David 70.0 大卫70.0
--> i: 1 ->我:1
Goliath 240.0 巨人240.0
David 40.0 大卫40.0
--> i: 2 ->我:2
Goliath 180.0 巨人180.0
David 10.0 大卫10.0
--> i: 3 ->我:3
Goliath 120.0 巨人120.0
David -20.0 大卫-20.0


For more reading: Value and Reference Types 有关更多阅读: 值和引用类型

After calling the method func attack(f: Fighter) -> Void every time, the properties of the Fighter who is being attacked are not getting updated. 每次调用func attack(f: Fighter) -> Void方法后,被攻击的Fighter的属性都不会更新。 So while loop is not going to break at any point. 因此, while循环在任何时候都不会中断。

Please replace the code below. 请替换下面的代码。

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
    }

When you're saying... 当你说...

    var g = f

...you're actually creating a copy of that object, not a reference. ...您实际上是在创建该对象的副本,而不是引用。 So, when you're changing 'health' property, you changing it in the copy. 因此,当您更改“健康”属性时,可以在副本中进行更改。 There are 2 simple solutions: 有两种简单的解决方案:

1) Change struct to class, 'cause classes are being referenced, unlike structs, which is just copying. 1)将struct更改为class,因为正在引用类,这与仅复制的struct不同。

2) Replace original object with its modified copy (g) 2)用修改后的副本替换原始对象(g)

As Rakesha notes, structs are value types, so your attack code doesn't actually modify anything: 正如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
}

(Side note: I think g.damage is incorrect here; I think you probably meant self.damage .) (旁注:我认为g.damage在这里不正确;我认为您可能是self.damage 。)

Nothing there actually modifies f . 那里实际上没有修改f There are several ways to address this. 有几种解决方法。 One is to use classes, which introduces subtle mutable state. 一种是使用类,它引入了微妙的可变状态。 I don't think I'd do that here. 我认为我不会在这里这样做。 By "subtle mutable state" I mean that you expect attack to modify f , but nothing in the signature says that it does that, so the caller may be surprised. “微妙的可变状态”是指您期望attack会修改f ,但是签名中没有任何内容表明它可以这样做,因此调用者可能会感到惊讶。

Instead, you have several ways to implement this that make your mutations explicit on structs. 相反,您有几种方法可以实现此目的,从而使您的突变在结构上明确。 You can make attack explicitly modify f : 您可以使attack明确地修改f

func attack(f: inout Fighter) {
    f.health = f.health - Double(damage * (1 - f.defense / 100))
}

Or you could turn it around and modify yourself when attacked by someone else: 或者,您也可以将其转为其他人攻击时进行的修改:

mutating func attackedBy(f: Fighter) {
    health = health - Double(f.damage * (1 - defense / 100)
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM