skip to content

Class Declarations & Members

The mechanics of declaring a class: constructors and init blocks, properties and their backing fields, custom accessors, visibility, and nesting. Interviewers probe here because initialization order and backing-field rules produce real bugs.

part ofKotlinoverview, primer and where to startread it →
on this pageshow

explore

questions

page 1 of 2

What is a computed property in Kotlin, and how do you write one using a custom get()?

level: juniorimportance: must knowfreq 70%

answer

  1. Custom get() = derived value
  2. No 'field' reference => no backing field
  3. Use val, recomputed every read
  4. Property for cheap/pure, function for expensive/params

basics

~10 s

A computed property has no stored value. Each time you read it, a custom get() runs and calculates the result on the fly from other data, instead of returning something saved in memory.

solid answer

~40 s

A computed property is a property whose value is derived on every read by a custom getter rather than stored. You declare it with `val name: T get() = expression`. Because the getter computes the value, Kotlin allocates no backing field (`field`) for it. It behaves like a zero-argument method but reads like a property, which keeps call sites clean (`person.fullName` not `person.fullName()`). Use `val` since there is nothing to store and assign. Common uses: `isEmpty get() = size == 0`, formatting, and aggregating other properties. Compared to a function, a computed property signals 'cheap, side-effect-free derived state'; expensive or parameterized work should stay a function.

code

kotlin · 4 lines
kotlin
class Order(val items: List<Item>) {
    val total: Double
        get() = items.sumOf { it.price }   // computed each read, nothing stored
}

go deeper

for a junior

Can write val area get() = width * height and explain it computes on read with no stored value.

for a middle

Articulates 'no backing field because field is never referenced' and recomputation on every access.

for a senior

Discusses property-vs-function style guidance (cheap/pure vs expensive/params) and lazy caching for hot paths.

for a principal

Frames computed properties as API design: predictable, side-effect-free reads, and the cost contract callers implicitly assume.

## What 'property' means in Kotlin A Kotlin property is a named member you read/write with field-like syntax (`obj.x`). Under the hood the compiler generates a getter (and a setter for `var`). For a normal property like `var x = 0`, the compiler also creates a hidden **backing field** — actual memory that stores the value. ## Computed property = custom get(), no backing field A **computed property** replaces the default getter with your own `get()` that returns a calculated value. Because the getter never refers to the special `field` identifier, the compiler generates **no backing field** — nothing is stored. The value is recomputed on every read. ```kotlin class Rectangle(val width: Int, val height: Int) { val area: Int get() = width * height // recomputed each read, no storage val isSquare: Boolean get() = width == height } ``` Key points: - Use **`val`**, not `var`: there is nothing to assign, so a setter makes no sense. - The getter can be written as an expression body `get() = ...` or a block `get() { ... return ... }`. - It runs **every** time the property is read, so each access re-evaluates the expression. ## Property vs function A computed property is semantically close to a parameterless function. Kotlin style guidance: prefer a **property** when it's cheap, has no side effects, and just describes derived state (e.g. `size`, `isEmpty`, `fullName`). Prefer a **function** when it's expensive, throws, or takes arguments. ```kotlin class Person(val first: String, val last: String) { val fullName: String get() = "$first $last" // property: cheap, pure fun greeting(lang: String) = "..." // function: takes a param } ``` ## Type inference caveat With a custom getter you usually still declare the type explicitly (`val area: Int`). Kotlin can infer it from the getter, but being explicit is the common, readable style.

  • Why use val and not var for a computed property?
    Because there is no stored value to assign; the value is derived from other state. A var would imply a setter, but you cannot meaningfully store into something that has no backing field.
  • Does the getter run once or on every access?
    On every access. If the computation is expensive, cache it (e.g. with `by lazy`) instead of recomputing each read.

Like a spreadsheet formula cell: it stores no number, it recalculates from other cells whenever you look at it.

saying these in an interview costs you the question

  • Claiming a computed property stores its result like a normal field
  • Saying the getter runs only once and is cached automatically
  • Using var for a derived property that has no backing field
  • Confusing it with a Java field plus getter method

context

open as a page

What is an `init {}` block in Kotlin, and when does its code run relative to the primary constructor?

level: juniorimportance: must knowfreq 70%

basics

~20 s

An init {} block holds setup code that runs when you create an object. It runs as part of the primary constructor, after the constructor parameters are available but as the object is being built.

open as a page

In Kotlin, what is the difference between a class declared inside another class with no modifier versus one declared with the `inner` keyword?

level: juniorimportance: must knowfreq 70%

basics

~20 s

By default a class inside another class is nested and standalone: it does not know about the outer object. Adding the inner keyword links it to an outer instance, so it can use the outer object's data.

open as a page

What is a Kotlin primary constructor, and how can it declare class properties directly in the class header?

level: juniorimportance: must knowfreq 80%

basics

~10 s

The primary constructor is written in the class header. If you put val or var before a parameter, Kotlin creates a property with that name automatically, so you don't write extra assignment code.

open as a page

What is the difference between a `val` and a `var` property in Kotlin, and what does the compiler generate for each?

level: juniorimportance: must knowfreq 85%

basics

~10 s

A val is read-only — you set it once and can't reassign it. A var can be reassigned. The compiler creates a getter for both, and a setter only for var.

open as a page

What is a secondary constructor in Kotlin, and how do you declare one?

level: juniorimportance: must knowfreq 60%

basics

~20 s

A secondary constructor is an extra way to create an object, written inside the class body with the constructor keyword. It lets you build an instance from a different set of arguments than the main one.

open as a page

What is the default visibility of a Kotlin class, function, or property when you write no modifier, and how does this differ from Java?

level: juniorimportance: must knowfreq 75%

basics

~10 s

In Kotlin, anything without a modifier is public, meaning visible everywhere. In Java, a member with no modifier is package-private, visible only within the same package.

open as a page

Explain the `field` identifier in a custom getter/setter. When does a property get a backing field, and what does referencing `field` mean?

level: middleimportance: must knowfreq 65%

basics

~10 s

Inside a custom getter or setter, field is a special name that refers to the property's own storage slot. The compiler only creates that storage if you actually use field, avoiding infinite recursion.

open as a page

What does `private set` do on a property, and how is it different from making the whole property private or using a val?

level: middleimportance: must knowfreq 60%

basics

~10 s

private set lets anyone read the property but only code inside the class change it. The outside world sees a read-only value; the class can still update it internally.

open as a page

Given multiple property initializers and `init` blocks in a class, what determines the order they execute in?

level: middleimportance: must knowfreq 65%

basics

~10 s

They run top to bottom in the order they are written in the class body. Property initializers and init blocks share one sequence — whichever appears first runs first.

open as a page

Inside an inner class, how do you access the outer class instance, and how do you disambiguate `this` when names collide between inner and outer?

level: middleimportance: must knowfreq 60%

basics

~20 s

Use a labeled this: this@Outer refers to the outer object and this@Inner (or just this) to the inner one. This lets you pick the right object when both define a property or method with the same name.

open as a page

How do default arguments in a Kotlin primary constructor work, and how do they interact with the JVM and named arguments?

level: middleimportance: must knowfreq 70%

basics

~10 s

You can give constructor parameters default values. Callers can leave those out, and Kotlin fills in the defaults. Named arguments let you skip earlier parameters while still setting later ones.

open as a page

What is the `field` keyword, and inside which scope is it available?

level: middleimportance: must knowfreq 75%

basics

~10 s

field refers to the property's hidden storage slot. You can only use it inside that property's getter or setter. It lets you read or write the stored value without calling the accessor again.

open as a page

When a class has a primary constructor, what rule governs secondary constructors, and how does this(...) delegation work?

level: middleimportance: must knowfreq 55%

basics

~10 s

If the class has a primary constructor, each secondary constructor must call it, directly or through another secondary constructor, using this(...). This guarantees the primary constructor always runs.

open as a page

What does private mean for a top-level declaration versus a class member in Kotlin?

level: middleimportance: must knowfreq 65%

basics

~10 s

A private top-level declaration is visible only inside its own file. A private class member is visible only inside that class (and its members), not to subclasses or outside code.

open as a page

What is `lateinit var`, what are its restrictions, and how do you safely check whether it has been initialized?

level: seniorimportance: must knowfreq 70%

basics

~10 s

lateinit var lets you declare a non-null property without setting it right away, promising to assign it before first use. Reading it too early throws an exception. You can check readiness with this::prop.isInitialized.

open as a page

When should you initialize a `val` directly in its declaration versus assigning it inside an `init` block? What can each do that the other cannot?

level: middleimportance: should knowfreq 40%

basics

~10 s

Use a direct initializer for simple values computed from one expression. Use an init block when assignment needs several statements, validation, or branching before you can decide the value.

open as a page

Why can declaring `inner` on a nested class cause memory leaks, and how does choosing nested instead help?

level: middleimportance: should knowfreq 45%

basics

~20 s

An inner class secretly holds a reference to its outer object, so as long as the inner instance is alive, the outer can't be garbage-collected. A plain nested class holds no such reference, so it lets the outer be freed.

open as a page

When is the constructor keyword required in a Kotlin primary constructor, and what does a private primary constructor enable?

level: middleimportance: should knowfreq 55%

basics

~10 s

Usually you skip the constructor keyword. You must write it when you add a visibility modifier like private, or an annotation. A private primary constructor stops outside code from calling it directly.

open as a page

Under exactly what conditions does the Kotlin compiler NOT generate a backing field for a property?

level: middleimportance: should knowfreq 60%

basics

~10 s

If the property's getter (and setter for a var) are fully custom and never use the field keyword, there's no stored value, so the compiler skips the backing field. The value is computed instead.

open as a page

In what order do the primary constructor's property initializers, init blocks, and a secondary constructor body execute?

level: middleimportance: should knowfreq 45%

basics

~10 s

First the primary constructor runs: property initializers and init blocks execute top to bottom. Then the secondary constructor's body runs afterward. So shared setup happens before the secondary-specific code.

open as a page

How does Kotlin's protected modifier behave, and how does it differ from Java's protected?

level: middleimportance: should knowfreq 50%

basics

~10 s

Kotlin's protected makes a member visible to the class and its subclasses only. Unlike Java, it does NOT add package-wide visibility, and it can't be used on top-level declarations.

open as a page

Your team debates whether a property may have a custom getter that does I/O or mutates state. What is the contract for getters/setters, and how do you decide between a computed property and a function?

level: seniorimportance: should knowfreq 30%

basics

~10 s

Property reads should feel cheap and harmless. Avoid getters that do slow work, throw, or change state. If it's expensive, has side effects, or takes inputs, make it a function instead.

open as a page

You add a validating custom setter to enforce an invariant, but invalid values still slip in. What are the ways a custom setter can be bypassed, and how do you close the gaps?

level: seniorimportance: should knowfreq 40%

basics

~20 s

A custom setter only runs on normal assignments. The property's own initializer skips it, constructor parameters can skip it, and reflection ignores it. To truly enforce a rule, validate in the constructor or init block too.

open as a page

What happens if an `init` block (or property initializer) reads a property declared later in the class? Show the failure mode.

level: seniorimportance: should knowfreq 45%

basics

~20 s

Reading a property before its initializer has run gives you trouble: usually the compiler rejects it, but in some cases the code runs and you see a default value like 0 or null instead of the real value.

open as a page

How do nested vs inner classes interact with generics and interface implementations on the outer class? For example, can a nested class implement an interface using the outer's type parameter?

level: seniorimportance: should knowfreq 30%

basics

~20 s

A nested class is independent, so it cannot use the outer class's type parameters or instance state. An inner class can, because it is tied to a specific outer instance and shares its generic context.

open as a page

Trace the initialization order when a primary constructor with val/var parameters runs alongside property initializers and init blocks. What pitfalls arise?

level: seniorimportance: should knowfreq 45%

basics

~20 s

First the constructor parameters get their values. Then property initializers and init blocks run from top to bottom in the order they appear. Using a property before it is set in that order can give you a null or wrong value.

open as a page

Explain the practical and performance differences between declaring a primary-constructor parameter as a property (val/var) versus a plain parameter.

level: seniorimportance: should knowfreq 50%

basics

~20 s

A val/var parameter is stored as a field for the object's whole life and is readable later. A plain parameter is only available while the object is being built, so it is not kept around.

open as a page

Explain property initialization order and how Kotlin properties surface to Java callers (including the `@JvmField` escape hatch).

level: seniorimportance: should knowfreq 45%

basics

~20 s

Properties and init blocks run top to bottom in the order they appear, after the primary constructor's parameters are set. From Java, Kotlin properties look like getX()/setX() methods unless you annotate the field with @JvmField to expose it directly.

open as a page

When should you prefer secondary constructors versus default parameter values or factory functions in Kotlin?

level: seniorimportance: should knowfreq 40%

basics

~20 s

Prefer default parameter values for simple optional arguments because they need less code. Use secondary constructors mainly when you need different parameter types, extra setup logic, or to satisfy frameworks and Java that call specific constructors.

open as a page

showing 1–30 of 36