There are a few options. The simplest approach is to use a wrapper class (#1); you can even use a sealed class (#2) so that when doesn't require an else branch. The downside of using a wrapper class is that wrapper classes can be far less efficient than using primitive types. That said, primitive types cannot be lateinit and a delegated property would probably be necessary in this use case, so a wrapper class could be a good idea.
The best answer is probably Option #3 - using inline classes. Inline classes should be optimised as if you were using the underlying primitive type, while providing the full benefits of OOP (unlike just using reflection). The downside of this is that they can't be sealed (so they'll require an else branch when using them with when) and that they're experimental.
Note that the code in the questions has a number of issues including missing is and else in the when expression and using lateinit with a primitive type.
Option #1:
class Foo { lateinit var property1: Foo.Property1 lateinit var property2: Foo.Property2 lateinit var property3: Foo.Property3 abstract class FooProperty class Property1(val value:String):FooProperty() class Property2(val value:Int):FooProperty() class Property3(val value:Long):FooProperty() } fun bar(fooProperty: Foo.FooProperty) { println( when(fooProperty) { is Foo.Property1 -> "Property1" is Foo.Property2 -> "Property2" is Foo.Property3 -> "Property3" else -> error("Impossible") } ) }
Option #2:
class Foo { lateinit var property1: FooProperty1 lateinit var property2: FooProperty2 lateinit var property3: FooProperty3 } sealed class FooProperty class FooProperty1(val value: String) : FooProperty() class FooProperty2(val value: Int) : FooProperty() class FooProperty3(val value: Long) : FooProperty() fun bar(fooProperty: FooProperty) { println( when (fooProperty) { is FooProperty1 -> "Property1" is FooProperty2 -> "Property2" is FooProperty3 -> "Property3" } ) }
Option #3:
inline class FooProperty1(val value:String) inline class FooProperty2(val value:Int) inline class FooProperty3(val value:Long) class Foo { var property1: FooProperty1 by Delegates.notNull() var property2: FooProperty2 by Delegates.notNull() var property3: FooProperty3 by Delegates.notNull() } fun bar(fooProperty: Any) { println( when(fooProperty) { is FooProperty1 -> "Property1" is FooProperty2 -> "Property2" is FooProperty3 -> "Property3" else -> error("") } ) }