Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

An extension property in Kotlin allows you to define a new property for an existing class (the receiver type) without modifying its source code or inheriting from it. Unlike regular properties, extension properties do not insert state into the target class or allocate memory for a backing field; they are resolved statically and rely entirely on custom accessors or property delegation.

Syntax

Extension properties are declared by prefixing the property name with the receiver type.
// Read-only extension property with custom getter
val ReceiverType.propertyName: PropertyType
    get() = /* computation based on 'this' */

// Mutable extension property with custom accessors
var ReceiverType.propertyName: PropertyType
    get() = /* computation based on 'this' */
    set(value) { /* mutation logic */ }

// Extension property using property delegation
val ReceiverType.delegatedProperty: PropertyType by DelegateClass()

Core Technical Constraints

  • No Backing Fields: Because extension properties do not modify the receiver class’s memory layout, they cannot store state. The field identifier is strictly prohibited within their accessors.
  • No Initializers: You cannot assign a default value directly to an extension property. A declaration like val String.customProp: Int = 5 will result in a compilation error.
  • Implementation Requirement: Since there is no backing field, an extension property must be implemented by explicitly providing custom accessors (get() for val, plus set() for var) or by using property delegation (by).
  • Static Dispatch: Extension properties are resolved statically at compile time based on the declared type of the reference, not dynamically based on the runtime type of the object.

Implementation Mechanics

Inside the custom accessors, the this keyword refers to the receiver instance.

Read-Only (val) Extension Property

A read-only extension property computes its value dynamically using the accessible API of the receiver object.
val String.lastCharIndex: Int
    get() = this.length - 1

Mutable (var) Extension Property

A mutable extension property must delegate its state to an existing mutable member of the receiver or an external state mechanism, as it cannot hold the state itself.
var StringBuilder.firstChar: Char
    get() = this[0]
    set(value) {
        this[0] = value
    }

Nullable Receivers

Extension properties can be defined on a nullable receiver type (Type?). This allows the property to be invoked safely on null references without requiring safe-call operators (?.). The custom accessor must explicitly handle the nullability of this.
val String?.isSafe: Boolean
    get() = this != null && this.isNotEmpty()

Companion Object Extension Property

If a class defines a companion object, you can declare extension properties on it. These are accessed using only the class name as the qualifier, mimicking static property access.
class HostClass {
    companion object { }
}

val HostClass.Companion.isSupported: Boolean
    get() = true

JVM Compilation Behavior

At the JVM bytecode level, Kotlin does not generate actual properties or fields for extension properties. Instead, they are compiled into methods. The characteristics of these generated methods depend on the declaration site and visibility modifiers:
  • Top-Level Declarations: When declared at the top level of a file, extension properties are compiled into static methods within a generated file-class (e.g., FileNameKt). A val generates a static getter, and a var generates both a static getter and setter. The receiver object is passed as the first parameter to these methods.
  • Object Declarations: When declared inside an object (singleton), extension properties are compiled into instance methods on the object’s singleton instance. They are only compiled into static methods if explicitly annotated with @JvmStatic. The receiver object is still passed as the first parameter.
  • Member Extension Properties: When an extension property is declared inside a class, it is compiled into an instance method of the declaring class (the dispatch receiver). It takes the extension receiver as its first parameter. It is subject to virtual dispatch regarding the dispatch receiver, while remaining statically dispatched regarding the extension receiver.
  • Visibility: The visibility of the generated methods strictly matches the visibility modifier of the property. For example, a private val String.customProp generates a private method, not a public one.
Master Kotlin with Deep Grasping Methodology!Learn More