Ooookay this ended up pretty long but I hope it helps at least!
That's not a constructor, because it's not constructing an object - it's just a function definition, and when you call that function, with singleBattle()
, you need to pass in the listed parameters by putting them in the parentheses.
Firstly yeah, those parameters passed into the function become local val
s inside the function block - they're read-only. You can do stuff with them, and assign the results to another val
or var
that you declare inside the function.
But I'm assuming what you're actually trying to do is something like this:
- A has access to variables like
finalBossHealth
- A passes
finalBossHealth
into function B (as enemyhealth
)
- B changes the value of
enemyHealth
- A sees that change in
finalBossHealth
because it's "the same variable"
which you can't do, because your parameters are fixed val
s. You basically have two options:
Define your variables outside the function, where A and B can both see them
So long as the function is in the same class as the variables (fields), it will be in the same scope and it'll be able to change them directly. In this case there's no real point in passing that value in, since it can read and write them directly
var enemyHealth = 9999
public fun singleBattle() {
enemyHealth = enemyHealth - 100
}
in practice you'd probably have a list of enemies or something, and you'd pass in an index so the function can look one up and modify it.
Return an updated value for A to use
This is the functional approach - you pass in certain data, the function does something with it, and passes a result out. Ideally if you pass the same data in, you get exactly the same result back each time - so it only relies on the parameters, not any state outside of the function (like fields in the class). If it doesn't have any side effects outside of the class (like changing a var
in the class) then it's called a pure function.
These are easy to reason about, because they just do one thing - put values in, get specific result, easy!
public fun singlebattle(enemyhealth : Int, enemyattack : Int , enemyname : String): Int {
// calculate whatever
return updatedHealth;
}
this one just returns an Int
, so the caller would call singleBattle
and then do something with the result. singleBattle
doesn't need to know anything about the external state, it just takes some values and does something useful with them.
If you need to return more than just one value (say the attack can decrease) you can create some kind of data structure that holds a bunch of values:
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)...
}
if you want to return more than one Fighter
(so you have the updated enemy state too) you might want to use another object that includes them both, like data class Battle(val fighter1: Fighter, fighter2: Fighter)
You can combine these (and lose the benefits of a pure function, but it might be easier to do things this way) by taking advantage of the fact you're passing references into a function:
// 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
}
this function doesn't return anything, because it's just changing the variables in those Fighter
objects that were passed in. The call passed in references to the player
and monster1
objects, not new copies, and although you can't change the value of fighter1
(i.e. which Fighter
object it refers to), you can poke around inside that object. And everything that can see that same object (has a reference to it) will see the updates. So after calling singleBattle(player, monster1)
you'll see the new values for player1.health
etc, because player1
points to the same Fighter
object in memory that fighter1
does while the function is messing with it.