Scope of variables in Kotlin Tutorial

In this section, we will learn about the scope of variables in Kotlin.

Definition of Scope: What Does Scope Mean for Kotlin Variables?

Scope of a variable is the area where a variable is accessible!

For example, if you declare a variable inside the body of a function, that variable is not accessible within the body of another function!

But if you declare a variable outside of the body of any function and inside the class itself (meaning set the variable as the property of that class) such variable (AKA property) will be accessible within the body of any function in that class! So any functions in that class can access the property, get its value or change it if necessary.

Alright, now let’s see in details the scope of variables when we declare them in different places.

Scopes of Variables in Kotlin

In short a variable can have any of these three scopes:

  • Class scope (AKA member variable)
  • Function scope (AKA local variable)
  • Block scope

Note: we have a global scope as well, which we’ve explained it in the Kotlin global and local variable section.

Kotlin Class Scope (AKA Properties)

A variable that is declared within the body of a class but outside the body of any function in that class has the Class Scope. (Note: we call such a variable as property!)

This type of variable is accessible within the body of any function declared inside the class. This means one function can, for example, call the variable and change its value if it wants to and another function can simply call the value to get its current value.

Example: class scope variable in Kotlin

class Employee{
    var name = "John Doe"

    fun getName():String{
        return "The name is: $name"
    }

    fun setName(fullName:String){
        name = fullName
    }
    
}

Here the name property is declared inside the body of the class and so its scope is Class Scope.

This means every function in this class (getName() and setName()) are able to access the property and get and change its value if they want.

Kotlin Function Scope (AKA Local Variable)

A local variable is a type of variable that we declare within the body of a function! The scope of this variable is limited to just the function that is declared within! Meaning you can’t access the variable from another function! Any attempt to do so would result an error.

Function Scope Notes:

  • In a function, we can’t have two variables with the same name!
  • But we can have two variables with the same name as long as their scopes differ from each other. For example, you can have a local variable with the name age and a property with the same name!
  • Two functions can also have variables with the same name. This is because each variable is declared in a separate function and so its scope is independent from the other.

Example: Function Scope Variable in Kotlin

class Employee{

    fun funcVar(){
        var name = "Jack Bauer"
    }

    fun printName(){
        println("The name is: $name")
    }
    
}

fun main(){
    var emp = Employee()
    emp.printName()
}

Output:

unresolved reference: name

In this example, there’s a local variable with the scope of function declared in funcVar function and named name. Now within the body of the printName() function, we’ve tried to access this variable and send its value to the output stream. But we can see that we got an error instead!

This is again because the scope of the variable is limited to its enclosing function and not the other functions! And so for this reason we got the error you see on the output stream.

Kotlin Block Scope (AKA Bracket Scope)

A block scope variable is a variable that is declared within the body of a block {}. For example, this block can be the block of an if statement, for statement, while statement, etc.

Each of these statements has its own block and if we declare a variable there, we can only access the variable within that boundary! Outside the boundary, it’s as if the variable did not exist at all!

Example: block scope variable in Kotlin

class Employee{
    var name = "John Doe"

    fun printName(){
        if (true) {
            var name = "Jack Bauer"
        }
        println("The name is: $name")
    }
    
}

fun main(){
    var emp = Employee()
    emp.printName()
}

Output:

John Doe

Here within the body of the printName() function we have a block scope variable that is defined within the body of the if statement. But as you can see, when we called the function to get the value of the name variable, we got the value John Doe which is the value of the property of this object!

Again, this is because the variable we’ve defined inside the if statement is limited to the border of that if statement and after that, it’s like the variable didn’t exist at all.

Shadowing Variable in Kotlin

Shadowing a variable happens when we have a local variable in a function with a name that a property of that class also has. In a situation like this, if we try to call the variable in the function, your program will invoke the value of the local variable instead of checking the value of the property of the class!

This is because our programs, when it comes to searching for a variable to get or change its value, they first start with the closest scope for the target variable!

For example, if we call for a variable within the body of an if statement, the program first start looking for the variable inside the body of the if statement itself!

Now if there wasn’t such a variable in the block, then the program will move one step out to see if the enclosing scope has such variable! If that scope (let’s say it’s the scope of a function that is declared inside a class) didn’t have the target variable, then our program continues to search for the variable in the enclosing scope of the function (which in this case it would be the class scope).

Now if the class also didn’t have a variable (property) with the specified name (including the search in the parent classes which we will explain this topic in the Kotlin inheritance section), then we will get an error.

But if the target variable was declared inside the enclosing function, for example, then our program will immediately use that variable to resolve the operation. So it won’t continue to search for the variable inside the body of the class (property). This is where variable shadowing happens.

Example: shadowing variable in Kotlin

class Employee{
    var name = "John Doe"

    fun printName(){
        name = "Omid Dehghan"
        println("The name is: $name")
    }
    
}

fun main(){
    var emp = Employee()
    emp.printName()
}

Output:

The name is: Omid Dehghan

Here the printName() function has a local variable named name and also we have a property with the same name.

Now when we called the function printName() we got the value of this local variable name and not the property with this name. (Basically, the property name is shadowed by the local variable we’ve declared in the function)

Again, this is because of the way our program searches for variables in a program.

Kotlin this Keyword

We mentioned how variable shadowing can happen in a function, but if we really want to access the value of a property in a class, Kotlin has provided a keyword called this which we can prefix the target variable’s name with this keyword and it signals the program that the target variable is actually the object property and not the local variable!

The this keyword is a reference to the current object that is invoking the target function!

For example, let’s say there’s an object named emp and it has a function named printSalary(). Here, if you call the printSalary() function using the emp object like emp.printSalary(), calling the this keyword inside the function would refer to the emp object.

Now let’s say the object has a property named salary.

So if we run a statement like this in the printSalary() function:

this.salary

It means we want to access the value of the salary property of the emp object.

(To make it simple, think of the this keyword as a variable created automatically for you and it refers to the object that invokes the target function).

Example: using the this keyword in Kotlin

class Employee{

    lateinit var firstName: String
    lateinit var lastName: String 
    var salary:Double = 0.0

    fun setNameAndLastName(fName:String, lName:String){
        firstName = fName
        lastName = lName
    }

    fun getNameAndLastName():String {
        return "The name is: ${this.firstName} and the last name is: ${lastName}"
    }

    fun putSalary(salary:Double){
        this.salary = salary 
    }

    fun giveSalary():Double{
        return this.salary
    }
}

fun main(){
    var john = Employee()

    john.firstName = "John"
    john.lastName = "Doe"

    john.putSalary(50000.0)

    println(john.getNameAndLastName())
    println(john.giveSalary())
}

Output:

The name is: John and the last name is: Doe

50000.0

Here we’ve used the this keyword in multiple functions of the Employee class and in every one of them, the this keyword will refer to the object that will invoke the enclosing function. Now take a look at this function, for example:

fun putSalary(salary:Double){

this.salary = salary

}

This function used the word salary for its parameter. But we know that there’s a property with the same name as well.

The purpose of this function is to take a value from users and assign that to the value of the salary property.

Now let’s say we didn’t use the this keyword to differentiate between the object’s property and the parameter of the function:

fun putSalary(salary:Double){

salary = salary

}

The problem here is that there’s no way for us (developers) as well as the Kotlin compiler to figure out which salary name is pointing to the property of the object and which one is pointing to the parameter of the function! Hence, an error will be thrown!

This is what the this keyword is trying to solve!

Facebook
Twitter
Pinterest
LinkedIn

Top Technologies