Programming in Kotlin: Fundamentals

Aug 9 2022 · Kotlin 1.6, Android 12, IntelliJ IDEA CE 2022.1.3

Part 3: Functions & Nullability

22. Write Custom Functions

Episode complete

Play next episode

Next
About this episode

Leave a rating/review

See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 21. Challenge: Use Nullables Next episode: 23. Return Data From Functions

Get immediate access to this and 4,000+ other videos and books.

Take your career further with a Kodeco Personal Plan. With unlimited access to over 40+ books and 4,000+ professional videos in a single subscription, it's simply the best investment you can make in your development career.

Learn more Already a subscriber? Sign in.

Transcript: 22. Write Custom Functions

In the previous parts of the course, you had to copy and paste code which you used multiple times. If these are smaller bits of code, then it wasn’t that big of a deal, but if you had to copy large pieces of code and change them according to some parameters, then you’re in trouble.

It takes a lot of time, and you can easily mess up your code, if you’re not careful.

[Slide 1 - Functions]

This is why you should separate code into functions.

Functions encapsulate pieces of code into reusable units which you can call and execute from anywhere, as long as you know about the function.

They can have parameters, which are the data it can receive, and it can return some piece of data, as its return type.

When you pass data to a function call, you’re passing in arguments. This is a very important distinction, so make sure to follow the naming conventions!

Functions also have a block of code they execute - the function body.

[Slide 2 - Function syntax]

The formal syntax is as follows:

You declare the keyword fun, because Kotlin is a lot of fun. Then you declare a function name, the parameters it can receive, and a return type, if there is one.

Finally you open a block of code using curly braces with create a scope for the function. And if the function has to return something, you need to call return at some point in your code, and that has to be the last statement in the scope.

Note, curly braces creates a scope as discussed in an earlier episode. This means that if you declare a variable inside a function, it cannot be accessed outside the scoep of the function. You’ll see how functions have their own scope in the demo section.

The whole idea of using functions in programming is to have a reusable block of code you can call whereever you need it. The println function is a very good example. Internally, it has the code that is responsible for printing output to the run panel. And you can see we have used it multiple times in different places.

Okay, let’s jump right in and we’ll start writing some custom functions.

Let’s create a simple function that just prints out a string. First you’ll create the function structure. Add in the following code:

fun printHello() {

}

This is a function declaration. And the part inside the curly braces is the body of the function. Just like with loops and if/else statements, that’s where you put the code you want to execute.

I just want this function to print out hello like so:

println("Hello")

And then to use or execute the function you need to call it from somewhere. Now to call the function, you just type the name of the function followed by parenthesis. Do this outside the function like so:

printHello()

And once you’ve called the function the code inside the body will be executed.

Go-ahead and run your app to see the output.

And there you have it, you have “Hello” printed out.

Now whats the difference between the methods you wrote in bullseye and the function you defined here? Why are some called functions and others methods?

Well, the function you just defined isnt inside a class.

While the methods you defined in Bullseye all belonged to the main activity class. So a method is just a function that belongs to a class.

If you didnt take “Your First Kotlin Android app” courses and dont understand what a class is, not to worry, you’ll learn about about classes down the learning path.

So this printHello function prints out the same message everytime. I’ll copy and paste the function call below. And then run the program. You see, it prints out hello twice.

Now, take a look at the println function. It prints out any string you pass to it. As you can see it is more dynamic.

If you hover over it, you can see a message in between the parenthesis in its definition. Anything you pass inside the parenthesis of the function declaration is called a parameter. println has one parameter; message, but a function can have multple parameters. Now println can print different messages depending on the data passed into it via its parameters.

Alright, lets make printHello print out a “Hello” then a name passed in via the parameter. Update your code to the following:

fun printHello(name: String) {
  println("Hello $name")
}

Now the printHello function accepts a string parameter called name. And you can already see we have errors where the function is called. If you hover over it, it says “No value passed for parameter name.”

The value you pass when calling the function is know as an argument. So you define parameter(s) in the function declaration then you pass arguments when calling the function. This is a very important distinction, so make sure to follow the naming conventions!

I’ll go ahead and pass in “Sam” and “Chris” as the arguments for first and second function calls respectively:

printHello("Sam")
printHello("Chris")

Then run the project, to see the output. You can see hello sam and hello chris printed out.

Now a function parameter can have a default value. Add “World” as default name in the function declaration like so:

fun printHello(name: String = "World") {
...

So the String “World” would be used as the default name if no name is passed while calling the function. Go ahead and add another function call but this time around dont pass any argument.

First, you’ll notice you dont have any error this time around. And that’s because the function definition has a default value for the name parameter.

Go ahead and run your code.

“Hello World” is displayed this time around. This can be useful in order to prevent errors where an operation requires a value.

One final thing to note is that a parameter of a function is a constant so this means that you cannot reassign it. Let me show you what i mean.

Enter the following code inside the function:

name = "Fela"

And immediately, you can see we have an error and if you hover over it, it says: “Val cannot be reassigned.”

I’ll clear that up now. Now, remember i mentioned that function creates their own scope and a scope is created using curly braces. So if i define a variable or constant inside the function like so:

...
val mood = "Happy"
...

It cannot be accessed outside the function. Try printing it outside the function:

...
println(mood)

And immediately it turns red to show that this is going to be a compile time error if we try to run the project. Hover over it. And it says that: “Unresolved reference: mood” and this is because you’re trying to access a variable or constant that does not exist in that scope. The mood constant is closed to the function in which it was declared because of the curly braces.

I’ll update the code with some comments so you have this in mind:

...
  val mood = "Happy" // Cannot be accessed outside this function
...
}
// Outside the function
//  println(mood) // would cause a compile-time error

Finally, when calling a function, you can name one or more of its arguments. This is useful when working with functions that have many parameters listed.

Update the printHello function to the following:

fun printHello(name: String = "World", isVeteran: Boolean = false) {
    if (isVeteran) println("Hello $name! Thank you for your service.")
    else println("Hello $name")
}

I’ll comment out the previous calls.

You can then call the function in any of the following ways:

printHello("Sam")
printHello(name = "Sam")
printHello(isVeteran = true)
printHello(name = "Sam", isVeteran = true)
printHello(isVeteran = true, name = "Sam")

As you can see with named argumeNts, the order in which you pass in the arguments dont matter.

Run the project, to see the output.

Do note that if a parameter doesnt have a default value then it must be placed in the correct order in which it was declared. For example, let’s remove the default value of the name parameter.

And immediately, you can see we have an error on the line where only the isVeteran boolean is passed. And if you hover over it, it says: “No value passed for parameter ‘name’” In this case, you’ll have to pass in the name argument at the first position.

printHello("Sam", isVeteran = true)

Run the project once more, to see the output.

In the next episode, you’ll learn about returning values from functions!