【问题标题】:Assign a variable a value through fucntions Kotlin通过函数 Kotlin 为变量赋值
【发布时间】:2021-01-16 08:16:37
【问题描述】:

当通过函数构造函数fun funname()创建变量时(这就是它们的名字吗?)似乎它们被声明为vals。由于vals不能重新赋值(我需要这样做是有原因的),我想知道是否有办法在函数之前的一行代码中将变量声明为var,然后通过函数赋值.

请记住,我昨天才开始学习 Kotlin。我对所有选择持开放态度。

public fun singlebattle(enemyhealth : Int, enemyattack : Int , enemyname : String)

当我尝试重新分配敌人生命值时,我收到错误“无法重新分配 val”,因此我尝试将 enemyhealth 和其他人声明为 vars

错误出现在这里:enemyhealth = enemyhealth - playerstats[1]

当我用玩家伤害减去enemyhealth来显示玩家受到攻击时

我正在使用 Repl.it Kotlin 版本 1.3.72

【问题讨论】:

  • 在函数的顶部,创建一个 var:var mutableEnemyHealth = enemyhealth,然后修改 thatmutableEnemyHealth = ...
  • 你能举个例子吗?我做了我认为你的意思,我得到了以下错误:property must be initialized or be abstract public var mutableEnemyhealth : Inta type annotation is required on a value parameter public fun singlebattle(enemyhealth = mutableEnemyhealth , enemyattack : Int , enemyname : String){
  • this answer 解释了吗?
  • 啊,是的。现在答案很清楚了,非常感谢你们,对于迟到的回复,我深表歉意。看来我需要跳出框框思考一下

标签: kotlin


【解决方案1】:

Ooookay 这很长,但我希望它至少有所帮助!

这不是一个构造函数,因为它不是构造一个对象——它只是一个函数定义,当你用singleBattle()调用那个函数时,你需要传入列出的参数,把它们在括号中。

首先,是的,传递给函数的那些参数在函数块内变为本地vals - 它们是只读的。您可以对它们进行处理,并将结果分配给您在函数中声明的另一个 valvar

但我假设你实际上想要做的是这样的:

  • A 可以访问变量,例如 finalBossHealth
  • A 将 finalBossHealth 传递给函数 B(作为 enemyhealth
  • B改变enemyHealth的值
  • A 看到 finalBossHealth 的变化,因为它是“同一个变量”

你不能这样做,因为你的参数是固定的vals。你基本上有两种选择:


在函数外部定义变量,A 和 B 都可以看到它们

只要函数和变量(字段)在同一个类中,它就会在同一个作用域中,并且可以直接改变它们。在这种情况下,传递该值没有任何意义,因为它可以直接读取和写入它们

var enemyHealth = 9999

public fun singleBattle() {
    enemyHealth = enemyHealth - 100
}

实际上,您可能会有一个敌人列表或其他东西,并且您会传入一个索引,以便该函数可以查找并修改它。


返回一个更新的值供 A 使用

这是函数式方法 - 您传入某些数据,函数对其进行处理,然后将结果传递出去。理想情况下,如果您传入相同的数据,每次都会得到完全相同的结果 - 所以它只依赖于参数,而不是函数之外的任何状态(如类中的字段)。如果它在类之外没有任何副作用(比如更改类中的var),那么它被称为 pure 函数。

这些很容易推理,因为它们只做一件事 - 输入值,获得特定结果,很容易!

public fun singlebattle(enemyhealth : Int, enemyattack : Int , enemyname : String): Int {
    // calculate whatever
    return updatedHealth;
}

这个只返回一个Int,所以调用者会调用singleBattle,然后对结果做一些事情。 singleBattle 不需要知道任何关于外部状态的信息,它只需要一些值并对它们做一些有用的事情。

如果您需要返回多个值(例如可以减少攻击),您可以创建某种包含一堆值的数据结构:

data class Fighter(val health: Int, val attack: Int, val name: String)

public fun singlebattle(player: Fighter, enemy: Fighter): Fighter {
    // calculate the player's state after the fight
    return player.copy(health = newHealth)
    // or just return Fighter(newHealth, player.attack, player.name)...
}

如果你想返回多个Fighter(这样你也有更新的敌人状态)你可能想使用另一个包含它们的对象,比如data class Battle(val fighter1: Fighter, fighter2: Fighter)


您可以利用将引用传递给函数的事实来组合这些(并失去纯函数的好处,但这样做可能更容易):

// I'm using vars here because we're gonna change them
data class Fighter(var health: Int, var attack: Int)

val player = Fighter(100, 999)
val monster1 = Fighter(9999, 5)

singleBattle(player, monster1)

fun singleBattle(fighter1: Fighter, fighter2: Fighter) {
    // do the fight, update the values
    fighter1.health = fighter1.health - fighter2.attack
    // etc... you can also say fighter1 -= fighter2.attack as a shorthand
}

此函数不返回任何内容,因为它只是更改传入的Fighter 对象中的变量。调用将引用 传递给playermonster1 对象,不是新副本,虽然您不能更改fighter1 的值(即它所指的Fighter 对象),但您可以在该对象内部四处寻找。并且所有可以看到同一个对象(有它的引用)的东西都会看到更新。所以在调用singleBattle(player, monster1) 之后,你会看到player1.health 等的新值,因为player1 指向内存中的同一个Fighter 对象,而fighter1 在函数搞乱它时所做的。

【讨论】:

  • 你为此努力过。绝对值得一票:D
  • 非常感谢,我的朋友。我为迟到,迟到回复道歉,因为我在学校。我认为您的回答确实帮助我理解了整个 kotlin 语言、变量处理以及我需要做什么才能获得我想要的结果。我将在数周甚至数月后再次提及这个答案。你的努力没有白费。
  • @Mike 是的,它涉及到很多不同的概念——如果你阅读范围、局部和全局变量、纯函数和副作用,以及对象和原语之间的区别,希望你会有一个很好的概述!范围对于 Kotlin 尤其重要,因此您可以了解这些东西到底发生了什么:kotlinlang.org/docs/reference/scope-functions.html 欢呼@mohsen!
猜你喜欢
  • 2021-09-16
  • 2022-01-20
  • 2023-02-09
  • 2018-03-12
  • 2018-06-06
  • 2018-04-03
  • 1970-01-01
  • 2018-07-08
  • 1970-01-01
相关资源
最近更新 更多