Overview:

In this tutorial, we are going to expand our understanding of Kotlin by making our application logic more modular. To do this we will be defining Functions, which are a mechanism for grouping our code and allowing easy re-use in other parts of the application. How to define a Function, Different types of Functions, and Refactoring existing logic into a Function – are some of the topics covered in this tutorial.

As a bonus, play close attention to the syntax of the println()functions used in the code samples. We demonstrate String Templating.

Requirements:

Source Code:
https://github.com/codetober.com/kotlin-functions

What is a Function?

A Function in Kotlin is a block of code that wraps pieces of code that we can reuse throughout our application. Defining a function is a key part of creating any Kotlin project; without functions, we would have to write all of the code for a particular operation every single time we wanted to use it – That’s just crazy!

Let’s start by looking at some sample code that represents customer orders at the MoonBucks cafe. Initially we have to write code to handle each customer order, however, we see in later examples that we can dramatically refactor this code for reuse and readability.

const val STORE_NAME = "MoonBucks"

fun main(args: Array<String>) {

    // Store Enter Text
    println("Welcome to $STORE_NAME! (No pictures please)\n")

    // First Order
    val drinkNameOne = "DarkSide Frap"
    val drinkPriceOne = 5.99
    val customerNameOne = "Carat"
    val drinkQtyOne = 2

    // Display order for first customer
    println("$customerNameOne orders $drinkNameOne(x$drinkQtyOne) for a total of \$${drinkPriceOne * drinkQtyOne}")

    // Second Order
    val drinkNameTwo = "Zero-Gravity Mocha"
    val drinkPriceTwo = 6.99
    val customerNameTwo = "Turbo"
    val drinkQtyTwo = 1

    // Display order for second customer
    println("$customerNameTwo orders $drinkNameTwo(x$drinkQtyTwo) for a total of \$${drinkPriceTwo * drinkQtyTwo}")

    // Store Exit Text
    println("\nThanks for shopping at $STORE_NAME! (Don't, tell your friends)")
}

Digging into the example

Notice that for every customer we represent, we had to create a new set of variables to hold the data. In a real application, these users would be passed to our application as arguments. In the section labeled, // First Orderwe’ve defined our data for the first customer; then, we print out the order to our console. We repeat this process for a second customer. Finally, we print an exit message for our cafe.

This process is not particularly efficient and would quickly become hard to maintain; if we wanted to change the output of the order we would have to change every single println(...) statement in our application. Yikes!

To streamline this process we will refactor the example code into several functions that achieve the same output.

  • Printing the order to console
  • Calculating the order price
  • Display welcome/exit output text

Creating a function to calculate drink price

In the example above, the total price of the drinks was calculated in line with our println(...) function: \$${drinkPriceOne * drinkQtyOne}. This is not particularly easy to read and is prone to errors. Instead, we will calculate the price of the order and return the value to another function to be printed.

private fun calculateDrinkPrice(drinkName: String, qty: Int): Double {
    val drinkPrice = when(drinkName){
        "DarkSide Frap" -> 5.99
        "Zero-Gravity Mocha" -> 6.99
        else -> 0.00
    }

    val drinkTotal = (drinkPrice * qty)
    return drinkTotal
}

This function combines many of the concepts from our previous tutorials in one small block of code, let’s break this down and explain it piece-by-piece.

private fun calculateDrinkPrice (drinkName: String, qty: Int) : Double {...}

Visibility Modifier

private indicates the visibility of the function. Private means that it can only be accessed within the same *.kt file. If you choose to omit the visibility modifier, Kotlin will default the value to public which allows access for any other Kotlin files or Classes to access the function by its name. Additionally, you could define a function with the protected or internal modifiers. Protected limits the use of the function to the current file or a sub-class in the same file. Internal limits the access of the method to files in the same Kotlin module.

Function Declaration

fun simply indicates to the compiler that a function definition follows this keyword.

calculateDrinkPrice is the name of the declared function. When we want to access this function from another place in our project we will call the function by its name. By convention, you should define functions using the “camel case” convention – lowercase first, then each subsequent word capitalized.

Function Parameters

(drinkName: String, qty: Int) indicate the parameters for the function. Each parameter has a name, type, and an optional default value. To provide a default value, just add it to the parameter definition. See the example below:

// Notice the use of a default value for the 'qty' parameter
private fun placeOrder(drinkName: String, customerName: String, qty: Int = 1){

    val drinkTotal = calculateDrinkPrice(drinkName, qty)
    println("$customerName orders $drinkName(x$qty) for a total of \$$drinkTotal")

}

Return Type

The last part of a complete function definition is the return type. After the function parameters, we indicate the type that the function will return. : Double so, our example will return a value of type Double to its caller.

Creating functions to print welcome/exit text

While defining a function it is possible to simplify the syntax when we want to wrap a single operation. In the case of our welcome and exit messages in the console, we only need to call the println() function. In the following snippet, we have excluded the return type as well as the curly braces that typically wrap functional code.

private fun printWelcomeMessage() =
        println("Welcome to $STORE_NAME! (No pictures please)\n")

private fun printExitMessage() = println("\nThanks for shopping at $STORE_NAME! (Don't, tell your friends)")

Now that we’ve seen all of the pieces of our original example refactored to use functions, all that remains is for us to call those functions from our main function in the application.

fun main(args: Array<String>) {
    printWelcomeMessage()

    // First Order
    placeOrder("DarkSide Frap", "Carat", 2)
    // Second Order with 'named params' - notice we left out 'qty' in favor of its default value
    placeOrder(customerName = "Turbo", drinkName = "Zero-Gravity Mocha")

    printExitMessage()
}

To view the full source code, check out the corresponding Github repository.

That’s it! Congratulations on making it all the way through this tutorial and continuing your quest to craft amazing code! If you liked this tutorial, please share it 🙂 Comment below with any questions or issues you faced.