Pop quiz: Anyone know why this fails to compile (a...
# getting-started
d
Pop quiz: Anyone know why this fails to compile (at least on JVM):
Copy code
@JvmInline
value class Namespace(val uri: String) {
}
open class WithNamespace(val namespace: Namespace) {
    constructor(url: String) : this(Namespace(url))
}
Spoiler: What type is Namespace on the JVM?
y
Conflicting signature for the constructor!
d
Exactly! I was only using the String overload, so I just removed the other constructor, but I'm wondering if there is a way to exclude the secondary from the JVM.
y
I mean, a factory function might be good enough:
Copy code
fun WithNamespace(url: String) = WithNamespace(Namespace(url))
d
The expected usage is:
Copy code
data object CalDav : WithNamespace("urn:ietf:params:xml:ns:caldav") {...}
I did get this to work, but its slightly more wordy: ``````
y
Oh yeah you could also do:
constructor(url: String, unit: Unit = Unit) : this(Namespace(url))
d
Copy code
interface Namespaced {
    val namespace: Namespace
}

@JvmInline
value class Namespace(val uri: String) : Namespaced {
    override val namespace: Namespace get() = this
    fun name(name: String) = Name(name, this)
}

data object CalDav : Namespaced by Namespace("urn:ietf:params:xml:ns:caldav") {
Yeah, thought about the
unit: Unit
. I think this is better though.
y
The interface solution is definitely way better tho. For the original, you could also do this for maximum compatibility:
Copy code
open class WithNamespace(val namespace: Namespace, val unit: Unit = Unit) {
    constructor(url: String) : this(Namespace(url))
}
Both constructors are accessible in Kotlin. The main constructor is (probably) marked synthetic or something, and the secondary constructor is accessible from Java.
e
k
The whole point of having a value class is to give you stronger typing, so you don't accidentally pass a plain
String
when you should be passing a
Namespace
. Why do you want to circumvent this by introducing a wrapper function/constructor?
d
This is a convenience for declaring the namespace values in the first place. In my example above, the CalDav object is the “source of truth” for this particular Namespace.