Values and Mutability In Kotlin: Getting Started
In this Values and Mutability tutorial, you’ll learn how to declare mutable, immutable, constant, late/lazily initialized, static & inline values. By Gabriela Kordić.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Values and Mutability In Kotlin: Getting Started
30 mins
- Getting Started
- Declaring Values
- Defining Immutable Values
- Defining Mutable Values
- Data Types and Default Values
- Using Late Initialization
- The Importance of Initializing Properties Before Use
- Using Lazy Initialization
- Declaring Constants
- Using Constants in Layouts
- Creating Singletons
- Distinguishing Object Expressions and Declarations
- Creating Companion Objects
- Omitting the Companion Object’s Name
- Using Static Values and Inlining
- Default Modifiers for Values in Companion Object
- Exposing Kotlin Static Properties in Java
- Inlining Properties
- Inlining Functions
- Where to Go From Here?
Values and mutability are features all programming languages need to provide. Have you ever had to declare a counter field or save an index of the last selected item in a list? Or did you need to save a license key for a third-party library such as Google Maps?
If the answer is yes, you most likely wondered if you should define those values inside or outside a class and which keywords you need to use. Considering Kotlin has several ways to define values across code, you probably had a hard time finding the best suitable solution.
Finally, here’s a tutorial to address all your doubts! :]
There are three possible ways of creating values in Kotlin — by using var, val and const val before a value name. In this tutorial, you’ll implement them and discover more about the differences between them.
More specifically, you’ll learn:
- How to declare mutable values, also known as variables, and where to use them
- How to declare immutable values and where to use them
- The difference between lazy initialization and late initialization
- The way to declare a constant and where to use it
- What a companion object is
- The difference between static values and inline values
Getting Started
Download the starter project by clicking the Download Materials button at the top or bottom of the tutorial.
In this tutorial, you’ll use the Tempco app. Tempco is a single-screen app for converting temperature values between Fahrenheit, Celsius and Kelvin measurement units.
Open the project in Android Studio. Build and run on a device to see how the app looks. Right now, you’re not able to experiment with conversions, but don’t worry, because you’ll implement all you need to use the app!
The app contains a ConstraintLayout
with one EditText
for inserting the desired temperature value, two Spinner
widgets for the initial and final measurement unit, and a TextView
for displaying a result. Every element of the layout has a TextView
above itself with instructions for use. It’s enough to interact with spinners to see the calculated result.
The app is quite simple, because the focus of the tutorial will be on values and declarations, instead of the Android UI!
Declaring Values
The first step for declaring values is to determine whether to declare it with val
or var
. What’s the real difference though?
First of all, a var
is also known as a variable, something that changes over time, whereas a val
is also known as a value, something that doesn’t change over time.
Both variables and values point to values and the terminology can be confusing, but values mean data in this case, and not a property you declare.
That being said, the keyword var is for mutable or non-final data, also knows as variables. You declare variables only if you’ll change the data it points to or the object it references to later.
Meanwhile, the keyword val defines immutable or final values and you can’t change their reference. It similar to the final variable in Java — it’s read-only.
It’s easy to differentiate between var and val, isn’t it? The terminology might be a bit confusing, but you’ll get the hang of it in no time! Now you’ll practice the implementation.
Defining Immutable Values
Open MainViewModel.kt and look for calculate()
. This function returns the result of temperature conversions. Add the following line to the top of it:
val temperatureValue: Double = value.toDouble()
Here, you’re defining an immutable value using val
. You’re using immutability because the variable is only used as a parameter in conversion — you won’t change it. Then, you’re setting up a return type as Double
and assigning the real value, which the user types in EditText
.
Now, use this new value in calculate()
. Since you already have conversion
and finalUnit
declared, use them and add the following code below finalUnit
:
conversionHelper.getConvertedValue(
conversion,
temperatureValue,
finalUnit,
::onSuccess,
::onError
)
In this code, you’re using three values and two lambdas using getConvertedValue()
. This function uses conversion
to find the right formula for the result temperature.
If the calculation succeeds, the system calls onSuccess()
and sends back the result. Otherwise, it calls onError()
and sends back a String
resource to inform the user.
In case you’re wondering if you could use a variable for temperatureValue
, the answer is: There’s no need. It’s only used inside calculate()
, and you don’t change it.
Defining Mutable Values
Now that you’ve mastered immutability, here’s a mutability task for you! In the same file, replace unitArray
with the following code:
var unitArray: Array<String> = emptyArray()
In this line, you declared a variable using var
. You set its name to unitArray
and the type as an Array
of String
items, with the default value of an emptyArray()
.
But why is this a variable? Right now, unitArray
is empty because of its default value, but to calculate the result, unitArray
needs to contain all the available units.
Consequently, you need to assign an appropriate array of units, and you use a variable to be able to change its value.
There are two reasons why you needed to assign an empty default array. First, the needed array exists in strings.xml. And to use resources, you need a Context. At this place in code, you don’t have access to a Context
, as it’s an Android dependency and you shouldn’t mix your business logic with the Android platform.
Second, variables need to be initialized straight away, be abstract, or use lateinit var
, which you’ll learn about later.
Data Types and Default Values
When using variables, you need to assign the default value. Otherwise, Android Studio throws an error that the variable either needs to be initialized or it needs to be abstract.
Try this out. Remove the default value of unitArray
. Your code will look like this:
var unitArray: Array<String>
You can see the error to set the default value.
Surely you’re wondering what to do if you don’t know which values to set by default, or what to do if you don’t have all the parameters you need at the moment. In the next section, you’ll learn what to do in such situations!