Inline classes cool feature, but there is some forbiddance I do not get why. The documentation says:
An inline class must have a single property initialized in the primary constructor. At runtime, instances of the inline class will be represented using this single property
So why is forced to have a public constructor? Ability to define private constructor could give a bit of flexibility.
For example, it would be nice to be able to use some preconditions for inline classes, I can imagine why inline classes can’t have to init block, but check could be done in a static method, something like this:
inline class URI private constructor(val value: String) {
companion object {
fun of(value: String): URI {
check(value.isNotBlank())
return URI(value)
}
}
}
Or an ability to “build” value, for example:
inline class URI private constructor(val value: String) {
companion object {
fun of(scheme: String, host: String, path: String): URI {
check(scheme == "http" || scheme == "https")
return URI("$scheme://$host/$path")
}
}
}
In some situation the runtime needs to create real instances of the Inline Class. Similar to how Java automatically auto-boxes primitive values in some situations. I assume this is the reason for the public constructor.
inline class NonEmptyString(val s: String) {
init {
check(s.isNotEmpty())
}
}
fun foo(s: NonEmptyString) = println(s.lenght) // should never print 0
If you look at the function from java it looks like this
void foo(String s);
So you would then call
foo("") // prints 0, which goes against the implementation of NonEmptyString
Thereby breaking the inline class.
The reason as I understand it is as follows. Kotlin can not guarantee that a constructor will be called when an inline class is created. Therefor (in order to ensure that inline classes don’t break) they can not have any logic in their constructor. Also since you can create an instance of an inline class without calling the constructor there is no point in restricting the visibility of the constructor.
I see now, public constructor limitation exactly to prevent such fabric methods, because of being unable to call it when passing parameter. Thanks for clarification
But you cannot be sure whether the instance came from your factory. Your factory might have been skipped by directly using constructor or providing parameter from Java code.