> ## 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.

# Kotlin Open Property

In Kotlin, properties are `final` by default in classes. An open property is a property that permits subclasses to override its accessors (getters and setters). To make a class property overridable, it must be explicitly marked with the `open` modifier. Conversely, properties declared within interfaces are implicitly open and do not require the `open` modifier. To override an open property, the subclass must use the `override` modifier.

```kotlin theme={"dark"}
interface Identifiable {
    val id: String // Implicitly open
}

open class Base : Identifiable {
    override val id: String = "BaseID"
    open var mutableProperty: Int = 0 // Explicitly open
}

class Derived : Base() {
    override val id: String = "DerivedID"
    override var mutableProperty: Int = 1
}
```

## Accessors and Backing Fields

When overriding an open property, you are overriding its accessors, not its backing field. Backing fields themselves cannot be overridden.

If a superclass property has a backing field and a subclass overrides that property with its own initializer, the compiler generates a *new* backing field specifically for the subclass. The superclass's backing field is still generated and initialized by the superclass constructor. Subclasses can access the superclass's property implementation (either its backing field value or its custom accessor logic) using the `super` keyword.

```kotlin theme={"dark"}
open class Entity {
    open val status: String = "Active" // Backing field initialized to "Active"
}

class AuditedEntity : Entity() {
    // Overrides the getter; no new backing field is generated here
    override val status: String
        get() = super.status + " (Audited)"
}
```

## Initialization Order Hazards

Accessing an open property within a superclass constructor or `init` block is inherently unsafe. During object instantiation, the superclass constructor executes before the subclass constructor. If the superclass constructor reads an overridden open property, it invokes the subclass's getter. Because the subclass has not yet been initialized, this will return an uninitialized value (such as `null`, `0`, or `false` depending on the type), often leading to `NullPointerException`s or corrupted state.

```kotlin theme={"dark"}
open class Parent {
    open val size: Int = 0
    init {
        // DANGER: Reads 'size' before Child initializes it. 
        // This prints 0, not 10.
        println("Size is: $size") 
    }
}

class Child : Parent() {
    override val size: Int = 10
}
```

## Overriding Rules, Mutability, and Type Variance

The compiler enforces strict rules regarding property mutability and type variance when overriding open properties:

* **Mutability Expansion (`val` to `var`):** You can override a `val` property with a `var` property. A `val` property contract only guarantees the existence of a getter. Overriding it with a `var` fulfills the getter contract while appending a setter.
* **Mutability Restriction (`var` to `val`):** You **cannot** override a `var` property with a `val` property. A `var` establishes a contract for both a getter and a setter; a subclass cannot remove the setter contract defined by its superclass.
* **Type Covariance for `val`:** When overriding a `val` property, the overriding property's type can be the same as, or a subtype of, the overridden property's type.
* **Type Invariance for `var`:** When overriding a `var` property, the overriding property's type must be **exactly the same** as the overridden property's type. Because a `var` includes a setter, allowing a subtype would violate type safety by restricting the types of values that could be assigned to the superclass reference.

```kotlin theme={"dark"}
open class SuperType {
    open val id: Number = 0
    open var name: CharSequence = "Unknown"
}

class SubType : SuperType() {
    // Valid: 'val' overridden by 'var', and 'Int' is a subtype of 'Number' (Covariant)
    override var id: Int = 1 
    
    // INVALID: Cannot override 'var' with 'val'
    // override val name: CharSequence = "Known" 
    
    // INVALID: 'var' must be invariant. Cannot change 'CharSequence' to 'String'
    // override var name: String = "Known"
    
    // Valid: Exact type match for 'var'
    override var name: CharSequence = "Known"
}
```

## Primary Constructor Overrides

Open properties can be overridden directly within the primary constructor of a subclass. This provides a concise syntax to declare the property and initialize its new backing field simultaneously.

```kotlin theme={"dark"}
open class Shape {
    open val vertexCount: Int = 0
}

class Rectangle(override val vertexCount: Int = 4) : Shape()
```

## Terminating the Override Chain

An overridden property is implicitly `open` to further subclasses. To prevent deeper subclasses from overriding the property again, the `final` modifier must be explicitly applied alongside `override`.

```kotlin theme={"dark"}
open class Intermediate : Base() {
    final override val id: String = "LockedID"
}
```

<div
  style={{ 
display: "flex", 
justifyContent: "space-between", 
alignItems: "center", 
maxWidth: "754px", 
padding: "1rem 0",
marginBottom: "24px"
}}
>
  <span style={{ fontWeight: "bold", fontSize: "1.25rem", color: "var(--tw-prose-headings)", fontFamily: "Inter, ui-sans-serif, system-ui, sans-serif" }}>Tired of Poor Kotlin Skills? Fix That With Deep Grasping!</span>

  <a
    href="https://syntblaze.com"
    target="_blank"
    style={{ 
  marginLeft: "24px",
  textDecoration: "none", 
  backgroundColor: "#007AFF",
  color: "#ffffff", 
  padding: "6px 16px", 
  borderRadius: "16px",
  fontSize: "0.9rem",
  fontWeight: "600",
  textAlign: "center",
  transition: "background-color 0.2s ease"
}}
  >
    Learn More
  </a>
</div>

<div style={{ display: "flex", gap: "12px", flexWrap: "wrap" }}>
  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/skill-tracking.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=b9b0305c93bb501c9e767b5c76c88835" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/skill-tracking.png" />

  <img src="https://mintcdn.com/syntblazellc/23tyuOzaWS88qFlc/images/nuggets.png?fit=max&auto=format&n=23tyuOzaWS88qFlc&q=85&s=c86c80197299762989e9b882419b2109" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/nuggets.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/bite-sized-exercises.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=a65f9a38c37ff28ab73ed783c53c60e3" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/bite-sized-exercises.png" />
</div>

<div style={{ display: "flex", gap: "12px", flexWrap: "wrap", marginTop: "12px" }}>
  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/mastery-chain.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=748a1763454713e679260fbb95f154a2" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/mastery-chain.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/element-previews.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=242f61448ff5dd6deaaab2dccc13b507" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/element-previews.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/element-explanations.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=cf0fc1c31f9cd0fc26716781be05fbc9" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/element-explanations.png" />
</div>
