Data and behavior
Fields and constructors give an object data. The other half of object-oriented code is behavior: things the object can do. In a class, that behavior is written as methods, which are functions declared inside the class body. A method can read and change the object's own properties.
Defining a method
A method is an ordinary function with fun, placed inside the class:
class Dog(val name: String) {
fun bark() {
println("Woof! I am $name")
}
}
The method uses the property name by its bare name. When you call rex.bark(), the method works on rex, so it sees rex's name. Another dog would print its own.
The parts of the declaration are the same as for any function: the keyword fun, a name, parentheses with parameters (empty here), an optional return type after a colon and the body in braces. With no return type, a method returns Unit, Kotlin's "nothing useful" value. Calling bark() and printing its result would show kotlin.Unit.
String templates
Inside a string, $name inserts the value of name. For anything more than a single name, use braces: "${name.uppercase()}!". To print a literal dollar sign, write \$.
Calling a method
Call a method on an object with the dot operator and parentheses:
val rex = Dog("Rex")
rex.bark()
This prints Woof! I am Rex. The parentheses are required: rex.bark alone is an error (function invocation 'bark()' expected). Passing arguments that the method does not take, as in rex.bark(1), is also an error.
Methods with parameters, return values and state
Methods can take parameters, return values, and change properties:
class Dog(val name: String) {
var tricks = 0
fun learn() {
tricks++
}
fun describe(): String {
return "$name knows $tricks tricks"
}
}
After rex.learn() has been called twice, rex.describe() returns Rex knows 2 tricks, while a second dog that never learned anything still reports 0 tricks. Each object keeps its own state, and a method only changes the object it was called on.
When the body is a single expression, Kotlin allows a shorter form: fun describe() = "$name knows $tricks tricks". The return type is inferred.
Method or property?
A good rule of thumb: if something describes what an object is, such as its name, make it a property. If it describes something the object does, or work it performs when asked, such as barking, make it a method. A method also suits a calculation that needs arguments, because a property cannot take any.
Methods calling methods
A method can call other methods of the same object by name, with no dot, and can refer to the object itself as this:
class Pup(val name: String) {
var energy = 5
fun run() { energy -= 2 }
fun report() { println("$name has energy $energy") }
fun train(): Pup {
run()
return this
}
}
After Pup("Rex").train().report() the output is Rex has energy 3. The train method returns the same object it ran on, so the next call can chain on it. Order of declaration inside the class does not matter: train may call a method written below it.
The exercise
The starter code defines Dog(val name: String) with an empty body, and mainFunction calls rex.bark(). The code does not compile until bark exists. The first step declares an empty method named bark in the class body. The second fills in the body so it prints "Woof! I am " followed by the name:
class Dog(val name: String) {
fun bark() {
println("Woof! I am $name")
}
}
class Solution {
fun mainFunction() {
val rex = Dog("Rex")
rex.bark()
}
}
The output is Woof! I am Rex. The val in the header matters: it makes name a property, and only properties are visible inside methods.
Common mistakes
- Defining the method outside the class. A function placed after the closing brace is a top-level function, not a method, and
rex.bark()will not find it. - Dropping
valfrom the constructor parameter. Withclass Dog(name: String), the method cannot seename. - Forgetting the parentheses on a call.
rex.barkdoes not call the method. - Changing the text. The lesson's tests compare the printed line exactly, so the spacing and capital letters in
Woof! I ammatter.
Key takeaways
- A method is a function declared inside a class, using
fun. - Inside a method, the object's properties are available by name.
- Call methods with a dot and parentheses:
rex.bark(). - Without a declared return type, a method returns
Unit. - Each object has its own state, and its methods act on that state.