Why does the Kotlin compiler emit a 'Expected classes are in Beta' warning, and what are the practical risks and alternatives when using `expect class`?
answer
- Beta = warning, not error; behavior may change
- expect fun/val stable; expect class still Beta
- @OptIn(ExperimentalMultiplatform::class) silences it
- libraries: prefer actual typealias / interface+factory
- apps: low risk, fix in one place on upgrade
basics
~20 sExpected classes are still marked Beta, so Kotlin warns you their behavior may change in future versions. For stable public APIs, many teams prefer matching a platform type with actual typealias or using interface + factory instead, reserving expect class for app-internal code.
solid answer
~50 sWhen you declare an `expect class`/`expect object`, the Kotlin compiler emits a warning that **expected classes are in Beta** and may change. This reflects that, unlike `expect fun`/`expect val` (stable), expected *classes* carry edge cases (member matching subtleties, supertype resolution, evolving rules) the team is still hardening, so source/behavior compatibility across compiler versions is not fully guaranteed. You can opt in with `@OptIn(ExperimentalMultiplatform::class)` or suppress via the compiler flag to silence it, but the pragmatic advice is: for **stable, published library APIs**, prefer `actual typealias` to map the expect onto an existing platform type, or model the seam as a common **interface** plus a platform-specific factory (`expect fun create(): MyApi`). Reserve `expect class` for application-internal seams where you control all callers and can adapt to changes. Functions and properties via expect/actual remain the lower-risk choice.
go deeper
Recognizes there is a Beta warning and that it does not stop the code from compiling.
Explains why classes (vs functions) are Beta and that the contract may change between compiler versions.
Weighs the library-vs-app risk and names alternatives (typealias, interface+factory) and how to opt in.
Sets a team policy: where expect class is acceptable, where to prefer stable seams, and how to insulate a public API from Beta-feature churn.
## The warning Declaring an expected class triggers a compiler diagnostic along the lines of *“Expected classes are in Beta. Their behavior and/or interface may be changed in future versions.”* It is a **warning, not an error** — your code compiles and runs. ## Why Beta? Expected **functions and properties** have been stable for a long time. Expected **classes/objects** involve trickier semantics: - member-by-member matching including constructors, supertypes, nested classes; - actualization-by-inheritance and via typealias; - interaction with sealed/enum/data/value classes; - how added members on the actual are governed. Because these rules are still being refined, the Kotlin team labels the feature Beta so the contract isn't frozen. ## Practical risks - A future compiler version could tighten or change matching rules, requiring small code changes. - For **libraries**, this is a real concern: your published API shape is tied to a Beta feature. For **apps**, you upgrade Kotlin and fix any breakage in one place, so the risk is low. ## Silencing the warning ```kotlin @OptIn(ExperimentalMultiplatform::class) expect class Foo() ``` or opt in project-wide via the compiler argument. Suppressing the warning does **not** change the Beta status — it just acknowledges it. ## Lower-risk alternatives 1. **actual typealias**: if a suitable platform type already exists, map to it instead of writing a fresh actual class. ```kotlin // commonMain expect class AtomicInt // jvmMain actual typealias AtomicInt = java.util.concurrent.atomic.AtomicInteger ``` 2. **Common interface + expect factory function** (functions are stable): ```kotlin interface Storage { fun save(k: String, v: String) } expect fun createStorage(): Storage ``` 3. **Keep expect class internal** to the app where you own all call sites. ## When expect class is still the right call When no platform type fits, you need a concrete shared type (not just an interface — e.g. for value semantics or to avoid an extra allocation), and you control the consumers. The Beta warning is then an acceptable trade-off.
- Does suppressing the Beta warning make the feature stable?No. Opting in only stops the diagnostic; the feature's contract is still Beta and could change in a future Kotlin release.
- For a published multiplatform library, what would you reach for instead of expect class?An actual typealias onto an existing platform type, or a common interface with an expect factory function, since those carry less compatibility risk.
saying these in an interview costs you the question
- Treating the Beta warning as a compile error that must be 'fixed' by abandoning KMP
- Believing @OptIn makes expected classes stable
- Recommending expect class for every library seam without weighing typealias/interface
- Confusing expect class Beta status with expect fun, which is stable
- Claiming the warning means runtime instability