Kotlin | Backing Fields
Kotlin auto-generates a field referencing a class property within its accessors "get() or set()". This field is called a backing field and it will be generated if a property uses the default accessors implementation or if one of the accessors references it through field
identifier.
Class Properties
val
&var
variables defined within the body of a class are called calss properties.
class SomeClass{
val id:Int = 2 // property "id" of type Int
var name:String = "" // property "name" of type String
}
- Class properties are accessible using properties names and dot notation on instances of the class.
- Properties declared as
val
are read-only i.e. have get(). - Properties declared as
var
are mutable i.e. have get() and set().
val someClass:SomeClass = SomeClass() // create an instance of class SomeClass
println(someClass.id) // getting value of id = 2
someClass.name = "SomeName" // setting value of name
println(someClass.name) // SomeName // getting value of name
- So, where are those
get()
andset()
defined?
Auto-Generated get()
& set()
- Kotlin, implicitly generates accessors function i.e.
get()
&set()
with default implementation for declared properties. - The default implementation of
get()
returns property value, while default implementation ofset(value)
assigns the passedvalue
to the property. get()
&set()
can be explicitly defined as shown below.
class SomeClass{
val id:Int = 2 // property "id" of type Int
get():Int { ... }
var name:String = "" // property "name" of type String
get():String { ... }
set(value):Unit { ... }
}
- So, how does
get()
return the property value?
This will generate StackOverflowError
!
- We may think that,
get()
returns the value of a property by simply using the property name e.g.get(){ return id }
. - Actually, this implementation will generate a
StackOverflowError
because we are making a recursive call to to the property.
class SomeClass{
val id:Int = 2 // property "id" of type Int
get():Int { return id } // recursive call StackOverflowError
var name:String = "" // property "name" of type String
get():String { return name } // recursive call StackOverflowError
set(value):Unit { name = value } // recursive call StackOverflowError
}
- So, how do
get()
&set()
refer to a property?
Backing field
- To avoid recursive call, Kotlin provides a backing
field
that will help you refer to a property within itsget()
&set()
functions. field
identifier can only be used in the accessors of the property.
class SomeClass{
val id:Int = 2 // property "id" of type Int
get():Int = field // default implementation
var name:String = "" // property "name" of type String
get():String = field // default implementation
set(value):Unit { field = value } // default implementation
}
- Kotlin provides a backing
field
automatically if it is used in the accessors i.e. if we override the default implementation of the accessors with a custom implementation that does not use backingfield
kotlin will NOT generate it.
val text:String = "ABCDEF"
val isEmpty: Boolean
get() = text.length == 0 // there will be no backing field
Properties without Backing Fields
- Backing fields are not available for properties in the following cases:
- Properties declared in interfaces.
- Properties annotated with
inline
modifier. - Extension properties
// 1. interface property
interface SomeInterface{
var ID:Int
get() = 3 // field is not allowed for inteface property
set(value){ } // field is not allowed for inteface property
}
// 2. inline property
class SomeClass{
inline var id:Int
get() = 3 // field is not allowed for inline property
set(value){ } // field is not allowed for inline property
}
// 3. extension property
val SomeClass.name:String
get() = "SomeName" // field is not allowed for extension property