Scope

Visibility keywords control who can see what.

Scope controls where things exist. This has an indirect impact on visibility: if something does not exist, it cannot be accessed by anything.

However, scope more directly controls things like garbage collection, as scope helps to determine the lifetime of objects.

Global

Top-level definitions in a Kotlin source file are global in scope. Immutable globals — classes, val, etc. — will exist for the life of the process that is executing the Kotlin code. Mutable globals — such as var — have references that will live forever, but the objects that those references reference might come and go as the value of that reference changes.

So, in this code, both the Foo class and the foo variable are global and immutable:

class Foo {
  fun something() {
    println("Hello, world!")
  }
}

val foo = Foo()

foo.something()

var bar = Foo()

bar.something()

bar = Foo()

bar.something()

bar too is considered to be global. The difference is that bar is mutable. So while anything that bar points to cannot be garbage collected, once bar is pointing to something else (e.g., another instance of Foo), whatever bar used to point to can be garbage collected.

Instance

Properties defined inside of a class have “instance” scope. Each instance of the enclosing class will have its own set of instance properties, independent of any other instance of that same class.

class Foo(val count: Int)

fun main() {
  val instanceOne = Foo(1)
  val instanceTwo = Foo(2)

  println(instanceOne.count)
  println(instanceTwo.count)
}

Here, each instance of Foo has its own count property with its own independent value.

Local

Any val or var within something smaller than a class is some form of local variable.

Local to Functions

A val or var directly inside of a function body is local to that function:

class Foo {
  fun something(message: String) {
    val length = message.length

    println("'$message' has $length characters")
  }
}

fun main() {
  Foo().something("this is a test")
}

Here, length is considered to be local to the something() function. You would be unable to access length from other functions on Foo, let alone from outside of Foo.

Local to Blocks/Lambdas

A variable defined within a block or lambda (i.e., chunk of code in {}) will be local to that block or lambda:

class Foo {
  fun something(messages: List<String>) {
    messages.forEach { message ->
      val length = message.length

      println("'$message' has $length characters")
    }
  }
}

fun main() {
  Foo().something(listOf("this", "is", "a", "test"))
}

Now length is not local to something(), but instead is local to the lambda expression supplied to forEach(). You cannot access length from elsewhere within something(), let alone from other methods on Foo or from outside of Foo.


Prev Table of Contents Next

This book is licensed under the Creative Commons Attribution-ShareAlike 4.0 International license.