Following similar patterns in other languages, I would be interested in producing the most useful way to strongly-type a primitive type in Kotlin.
The rationale, of course, is to have two types which are basically primitive (e.g. strings), but which cannot be assignable to each other by mistake.
My latest attempt is given here, and I'm interested to know how can it be minimized further (can defining the derived constructor be omitted?)
abstract class StronglyTyped<T>{
private var value: T
constructor(_value: T) {
value = _value
}
operator fun invoke(): T {
return value
}
}
class UserId: StronglyTyped<String> {
constructor(_value: String): super(_value) {}
}
class UserName: StronglyTyped<String> {
constructor(_value: String): super(_value) {}
}
fun main() {
val a = UserId("this is a userId")
val b = UserName("this is a userName")
var c: UserName
//c = a // <== won't compile
c = b
println(c())
}
CodePudding user response:
Sounds like you're looking for value class
es. More information is available in the official documentation.
An example might look something like the following:
value class Password(val value: String)
If you want to enforce some validation on the primitive, you can do so inside the init
block.
value class UserId(val value: String) {
init {
require(value.length == 8) { "A userId must be exactly 8 characters long!" }
}
}
Note however, that this just provides compile-time type safety, because the original primitive types are used during the runtime.