Swift 4:如何让函数修改外部变量
问题原因&解决方案
嘿,这个问题我太熟悉啦!你碰到的是Swift里值类型和引用类型的核心区别问题~
为什么外部的enemyTwoHP没变化?
因为你定义的Enemy和Player都是结构体(struct),而结构体是Swift里的值类型。当你把enemyTwo传入attackTarget函数的target参数时,Swift会自动创建一个target的完整副本——你在函数里修改的attackTAR其实是这个副本的另一个副本,完全碰不到外面的原始enemyTwo实例,所以函数内打印的是副本的HP,外部打印的还是原始实例的初始值。
两种快速解决方法
方法1:用inout关键字让参数支持修改原始值
把函数的target参数标记为inout,这样Swift就会直接操作原始实例,而不是创建副本。修改后的代码如下:
struct Player { var maxHP: Int var currentHP: Int var maxMP: Int var currentMP: Int var currentLVL: Int var damageATT: Int } struct Enemy { var maxHP: Int var currentHP: Int var damageAtt: Int } var alexRider = Player(maxHP: 100, currentHP: 100, maxMP: 100, currentMP: 100, currentLVL: 1, damageATT: 5) var enemyTwo = Enemy(maxHP: 40, currentHP: 40, damageAtt: 4) // 修改函数参数为inout func attackTarget(attacker player: Player, enemy target: inout Enemy) { target.currentHP -= player.damageATT print("Dealt \(player.damageATT) damage!") print("Enemy now has \(target.currentHP) health remaining") } // 调用时要在参数前加&符号 attackTarget(attacker: alexRider, enemy: &enemyTwo) print(enemyTwo.currentHP) // 现在会输出35啦!
方法2:把Enemy改成类(class)
类是Swift里的引用类型,传递参数时传递的是实例的引用,函数里修改的就是原始实例的属性。修改后的代码如下:
struct Player { var maxHP: Int var currentHP: Int var maxMP: Int var currentMP: Int var currentLVL: Int var damageATT: Int } // 把Enemy从struct改成class,需要手动添加初始化器 class Enemy { var maxHP: Int var currentHP: Int var damageAtt: Int init(maxHP: Int, currentHP: Int, damageAtt: Int) { self.maxHP = maxHP self.currentHP = currentHP self.damageAtt = damageAtt } } var alexRider = Player(maxHP: 100, currentHP: 100, maxMP: 100, currentMP: 100, currentLVL: 1, damageATT: 5) var enemyTwo = Enemy(maxHP: 40, currentHP: 40, damageAtt: 4) // 函数不需要修改,直接使用即可 func attackTarget(attacker player: Player, enemy target: Enemy) { target.currentHP -= player.damageATT print("Dealt \(player.damageATT) damage!") print("Enemy now has \(target.currentHP) health remaining") } attackTarget(attacker: alexRider, enemy: enemyTwo) print(enemyTwo.currentHP) // 同样会输出35!
怎么选?
- 如果你的敌人需要独立的副本(比如生成多个完全一样但状态独立的敌人),优先用struct + inout的组合,符合值类型的设计初衷。
- 如果敌人是需要共享状态的实例(比如全局唯一的Boss),用class更合适,引用类型的特性会让状态修改更直接。
内容的提问来源于stack exchange,提问作者QuantamPulse
相关产品推荐
相关产品推荐

