Classes & Objects
Kotlin's object model end to end: constructors and properties, data, sealed and value classes, enums, objects and companions, inheritance rules, and built-in delegation. This is the largest everyday surface of the language and interviews reflect that.
part ofKotlinoverview, primer and where to startread it →on this pageshowhide
explore
- How Kotlin Does Classes & Objects5 questions
- Class Declarations & Members36 questions
- Primary Constructor5 questions
- Secondary Constructors & this() Delegation5 questions
- init Blocks & Initialization Order5 questions
- Properties & Backing Fields5 questions
- Custom Getters & Setters5 questions
- Visibility Modifiers & internal6 questions
- Nested vs inner Classes5 questions
- Data Classes21 questions
- data class & Generated Members5 questions
- componentN() & Destructuring6 questions
- copy() & Immutable Updates5 questions
- Data Class Constraints5 questions
- Sealed Types20 questions
- sealed class & sealed interface5 questions
- Exhaustive when over Sealed5 questions
- Sealed for State Modeling (ADTs)5 questions
- Sealed vs Enum5 questions
- Value / Inline Classes15 questions
- value class & @JvmInline5 questions
- Boxing & Unboxing Rules5 questions
- Use Cases & Limits5 questions
- Enum Classes20 questions
- enum class & Members5 questions
- Enums with Behavior5 questions
- Enums Implementing Interfaces5 questions
- entries vs values()5 questions
- Objects & Companions21 questions
- object Declarations (Singletons)5 questions
- companion object5 questions
- Companion as Factory6 questions
- Object Expressions / Anonymous Objects5 questions
- Inheritance & Interfaces25 questions
- open / final by Default5 questions
- override & super5 questions
- Abstract Classes5 questions
- Interface Default Methods & Properties5 questions
- Diamond Resolution (super<T>)5 questions
- Delegation10 questions
- Class Delegation by5 questions
- Delegation vs Inheritance5 questions
questions
173 · 9 sectionsIn Kotlin, what are the default visibility and inheritance modifiers for a top-level class declared with just `class Foo`, and why were those defaults chosen?
basics
~10 sA plain Kotlin class is public so any code can use it, and final so nobody can subclass it. To allow subclassing you must write the keyword open.
Kotlin makes singletons a first-class language feature with `object`. Describe object declarations, companion objects, and object expressions, and how each is initialized.
basics
~20 sobject Foo { } declares a single, lazily created instance — a built-in singleton. A companion object is the one singleton attached to a class for 'static-like' members. An object : Type { } expression creates a one-off anonymous object on the spot.
Explain how Kotlin's primary constructor can declare properties inline, and what `val`/`var` in the constructor header does versus a plain parameter. When do you need an `init` block or a secondary constructor?
basics
~10 sPutting val or var before a primary-constructor parameter makes it a stored property of the class in one line. Without val/var it's just a constructor argument. init blocks run setup code at construction.
Kotlin makes delegation a language feature via the `by` keyword for both interfaces and properties. Explain class/interface delegation and property delegation, and what the compiler generates.
basics
~20 sby lets one object hand off work to another automatically. For interfaces, a class can implement an interface by forwarding all its methods to a held object. For properties, getting/setting a value can be routed through a helper like lazy or Delegates.observable.
Kotlin maps OOP onto the JVM with opinionated defaults (final classes, no statics, language-level delegation). As an API designer, what are the consequences of these choices for library evolution, Java interop, and framework integration?
basics
~20 sKotlin's defaults make code safer and shorter but require extra care: final classes can block frameworks that subclass your types, and 'no statics' plus companions need annotations for clean Java use. Plan these at the API boundary.
What is a computed property in Kotlin, and how do you write one using a custom get()?
basics
~10 sA 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.
What is an `init {}` block in Kotlin, and when does its code run relative to the primary constructor?
basics
~20 sAn 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.
In Kotlin, what is the difference between a class declared inside another class with no modifier versus one declared with the `inner` keyword?
basics
~20 sBy 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.
What is a Kotlin primary constructor, and how can it declare class properties directly in the class header?
basics
~10 sThe 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.
What is the difference between a `val` and a `var` property in Kotlin, and what does the compiler generate for each?
basics
~10 sA 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.
What is a destructuring declaration in Kotlin, and what makes `val (a, b) = point` work under the hood?
basics
~10 sIt lets you pull several values out of one object in a single line, like val (x, y) = point. Kotlin does it by calling special functions named component1(), component2(), and so on.
What does the generated copy() function on a Kotlin data class do, and why is it useful for immutable data?
basics
~10 scopy() makes a new object that is the same as the old one, except for the properties you choose to change. The original stays untouched, so you update data without modifying it in place.
What members does the Kotlin compiler auto-generate when you mark a class as a `data class`, and what drives their content?
basics
~10 sMarking a class data makes the compiler write equals(), hashCode(), and toString() for you, based on the properties declared in the primary constructor, so you don't write that boilerplate by hand.
What are the requirements on a data class's primary constructor, and why won't `data class Empty()` compile?
basics
~20 sA data class must declare a primary constructor with at least one parameter, and every parameter must be marked val or var. An empty parameter list, or a plain parameter without val/var, is a compile error.
Exactly which properties of a data class get a generated componentN(), and what gotchas does that create for destructuring?
basics
~10 sOnly the properties listed in the data class's main constructor get componentN() functions, in the order they're written. Properties declared inside the class body don't get one, so you can't destructure them.
What is a sealed class (or sealed interface) in Kotlin, and what does the sealed modifier guarantee about its subtypes?
basics
~20 sA sealed class or interface is one where the compiler knows the complete, fixed list of all its direct subtypes. New subtypes can't be added from outside, so the set of possibilities is closed and known at compile time.
When you use `when` as an expression over a sealed type and cover every subtype, why don't you need an `else` branch?
basics
~10 sBecause the sealed type lists all its possible subtypes in advance. If you handle each one, the compiler knows nothing else is possible, so an else branch would be pointless.
You need to represent a screen that can be loading, show data, or show an error. How would you model this with a sealed type, and why is that better than three nullable fields?
basics
~10 sMake a sealed type with three cases: Loading, Success holding the data, and Error holding a message. Only one case can exist at a time, so you can never have a half-loaded, half-errored screen.
What is the core difference between a Kotlin enum class and a sealed class/interface, and when would you reach for each?
basics
~20 sAn enum is a fixed set of named constant objects that all look the same. A sealed type is a closed set of subclasses that can each have different fields and many instances. Use enum for simple constants, sealed for varied data.
Where are subtypes of a sealed class or interface allowed to be declared? Explain the same-module / same-package permitted-subtype rule.
basics
~20 sDirect subtypes must be in the same module as the sealed declaration, and in the same package. You can nest them inside the sealed type or put them in separate top-level files, as long as they stay in that module and package.
What does it mean for a Kotlin @JvmInline value class to be "boxed," and when does the compiler keep it inlined (unboxed) instead?
basics
~20 sNormally the value class disappears and only its single wrapped value is used directly, which is fast. Sometimes Kotlin must wrap it back into a real object (boxing), like when it is null or stored generically.
What is a Kotlin value class, and why must it be annotated with @JvmInline on the JVM?
basics
~20 sA value class wraps one value (like a String or Int) in a new type without the cost of a real object. On the JVM you add @JvmInline so Kotlin can store just the wrapped value instead of a wrapper object.
Why would you wrap a String or Long in a value class such as UserId or Email instead of using the raw primitive type directly?
basics
~20 sTo make the type meaningful and safe. A plain String could be anything; a UserId can only be a user id, so the compiler stops you from mixing up a user id with an order id or an email.
At runtime, how does the Kotlin compiler represent a @JvmInline value class, and what does the underlying property's type have to be?
basics
~10 sWhere possible the compiler throws away the wrapper and uses the wrapped value directly, so there's no extra object. The single property can hold almost any type, including another value class.
What are the structural constraints on a value class — how many properties can it have, and can it have ordinary properties with backing fields?
basics
~10 sA value class must have exactly one value (one constructor property). It can't have extra stored properties — only computed ones. That single value is what it really is underneath.
How do you declare an enum class in Kotlin, and what is an enum constant?
basics
~10 sWrite enum class Name { A, B, C }. Each capitalized name inside the braces (A, B, C) is a constant — a fixed, named instance of that enum that you reference as Name.A.
In Kotlin, how do you make each enum constant run its own different code for the same operation? Show a small example.
basics
~10 sDeclare an abstract function in the enum, then give each constant a body in curly braces that overrides it. Calling the function on a constant runs that constant's version.
What is the `entries` property on a Kotlin enum class, and how does it differ from the older `values()` function?
basics
~10 sentries gives you all the constants of an enum as a read-only list. The old values() did the same but returned an array, and it made a brand-new copy every time you called it.
How does a Kotlin enum class implement an interface, and how can the implementation differ per enum constant?
basics
~10 sPut the interface name after a colon in the enum header. You can implement the interface once for all constants, or let each constant override the method with its own version inside its body.
How do you give each enum constant constructor parameters, and how are those values supplied per constant?
basics
~10 sAdd a constructor to the enum class, then put the argument values in parentheses after each constant, like RED(0xFF0000). Each constant supplies its own values, and you read them as normal properties.
How do you create a class whose only way to be constructed is through a named factory function on its companion object, hiding the real constructor?
basics
~10 sMark the constructor private and add a function in the companion object that creates and returns the instance. Callers use the named function instead of calling the constructor directly.
What is a companion object in Kotlin, and how do you call its members?
basics
~10 sIt is a special object declared inside a class with the 'companion object' keywords. Its properties and functions can be called using the class name directly, without creating an instance.
What does an `object` declaration create in Kotlin, and how is it different from a regular `class`?
basics
~10 sAn object declaration creates a singleton: exactly one instance that Kotlin makes for you. You never call a constructor. You use it by its name, like Counter.next().
What is a Kotlin object expression (anonymous object), and when would you use one instead of a named class?
basics
~20 sAn object expression creates a one-off, unnamed instance on the spot, often to implement an interface like a click listener. You use it when you need a single instance and don't want to write a whole named class.
When is an `object` declaration initialized, and what guarantees does Kotlin give about thread-safety of that initialization?
basics
~10 sThe object is created the first time something accesses it, not at program start. Kotlin makes sure this happens only once even if many threads hit it at the same time.
What is an abstract class in Kotlin, and how do you declare an abstract member that subclasses must implement?
basics
~10 sAn abstract class is one you cannot create objects from directly. It can have members marked abstract that have no body, and any non-abstract subclass must provide their implementation.
A class implements two interfaces that both provide a default implementation of the same method foo(). What does Kotlin require you to do, and why won't it compile otherwise?
basics
~10 sBoth interfaces give a body for the same method, so Kotlin can't pick one for you. You must override the method in your class. Otherwise the compiler reports an error and refuses to build.
In Kotlin, can an interface provide a default implementation for a method? Show how and explain what a class gets when it implements that interface.
basics
~10 sYes. A Kotlin interface method can include a body. Classes that implement the interface inherit that body for free and only need to override it if they want different behavior.
In Kotlin, are classes open for subclassing by default? What do you write to allow a class to be subclassed?
basics
~10 sNo. By default Kotlin classes are final, so you cannot extend them. To allow subclassing you mark the class with the open keyword.
In Kotlin, why is the `override` keyword mandatory when redefining a member from a superclass or interface, and what happens if you omit it?
basics
~10 sYou must write override before a function or property that replaces one from the parent. It makes your intent explicit. If you forget it, the code does not compile.
What does the `by` keyword do when a class declares `class MyList(impl: List<String>) : List<String> by impl`?
basics
~10 sIt makes the class implement the List interface by automatically forwarding every interface method call to the impl object you pass in, so you don't write those methods by hand.
In Kotlin, what does it mean to implement an interface 'by' delegating to another object, and why might you prefer that over extending an open base class?
basics
~20 sThe 'by' keyword lets a class implement an interface by handing every method call to another object you give it. You reuse behavior by wrapping an object instead of subclassing it, so you don't depend on a parent class's internals.
When you override a member in a class that uses `by` delegation, do the OTHER auto-forwarded members start calling your override or the delegate's own implementation? Explain the trap.
basics
~20 sOther forwarded methods still call the delegate's own versions, not your override. The delegate doesn't know about your wrapper, so any internal calls it makes go to itself. Your override only affects calls made directly on the wrapper.
When you write `class W(impl: Foo) : Foo by impl`, is the `impl` value stored and accessible inside the class? How do you access the delegate if you need it?
basics
~10 sThe compiler stores the delegate in a hidden field, but a plain constructor parameter is not a property, so you can't reference it later. To use it inside the class, declare it as val.
In a class using interface delegation, if you both delegate to an object and explicitly override one method, which implementation runs — and does the delegate still see the override?
basics
~10 sYour explicit override always runs for that method. But the delegate object never knows about your override — if it calls another of its own methods internally, it calls its own version, not yours.