【问题标题】:Struct mutating func calling a func in another instance of the same struct结构变异函数在同一结构的另一个实例中调用函数
【发布时间】:2018-02-09 03:34:51
【问题描述】:

我今天正在快速学习结构和课程,并决定尝试使用我新发现的知识来简化我之前构建的战斗计算器。现在我明白了,在 func 中调用的属性本质上是局部变量,更何况是“让”常量。所以我知道为什么下面的代码有错误,但我不知道如何在不使用 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()

【问题讨论】:

    标签: swift struct swift4 local-variables mutating-function


    【解决方案1】:

    您只需要使用 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()
    

    这将打印出来

    玩家 1 正在攻击玩家 2...

    玩家 1 对玩家 2 造成 3 点伤害!

    当前生命值是:玩家 1:10 和玩家 2:12


    另一个选择是使用类而不是结构。您需要为您的类提供一个自定义初始化程序并从您的方法中删除 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()
    

    【讨论】:

    • 另一个选择是使用类而不是结构。您需要为您的类提供一个自定义初始化程序并从您的方法中删除 mutating 关键字
    • 我不需要为每个单元创建一个单独的类,因为引用的是数据而不是它自己的单独副本吗?
    • 好酷。我想我对结构和类之间的区别有误解。我将不得不做更多的学习。非常感谢您的帮助@LeoDabus
    猜你喜欢
    • 2022-10-23
    • 1970-01-01
    • 2014-08-01
    • 2012-06-22
    • 2014-03-12
    • 2017-07-08
    • 1970-01-01
    • 1970-01-01
    • 2016-08-17
    相关资源
    最近更新 更多