Quick "getting started" type question - is this a ...
# getting-started
Quick "getting started" type question - is this a valid definition of a data class?
data class Name(val title: String, val lowerTitle = title.lowercase())
? I.e. a default value dependent on the value of another field? It seems to compile...
nitpicking on the example itself, A class like this would let me create a
moving lowerTitle into a val outside the constructor is probably what you really want. The only downside is that it won't be a part of the toString method
In real code, it's not just lowercase. And it needs to be in the constructor because it's a Serialized class. It's working but I'm not sure it's a good idea, as you say, could be open to abuse.
also keep in mind calling
will break the relationship between these properties
They are allowed to be unrelated in my usecase, it's more about providing a calculated default value if the "lowerTitle" isn't supplied. Though ideally I'd want some sort of contract in place to ensure the value is valid... The true class is:
Copy code
data class PostMetadata(val title: String, val template: String = "post", val slug: String = title.toSlug(), val date: LocalDate)
// and String extension function 'toSlug()'...
fun String.toSlug() : String {
    val reserved = "[;/?:@&=+\$, ]"
    return this.replace(Regex(pattern = reserved),"-").lowercase()
I do feel I'm abusing power here.
I think it's fine - but I'd define a
class (as a
value class
if that works OK for you) and enforce the invariant in its constructor.
Thanks @Rob Elliot - I have yet to learn value classes (though I'm suddenly, pointlessly, exploring context receivers when I should be focusing on more important things!)
Doesn't have to be a value class, could be a plain old data class with one value. The important bit is that by having a checked type that enforces the invariant you ensure that you can't end up with an invalid slug.
A value class is just a way to get that without actually boxing the string in another object in memory. Basically
value class Slug
only exists at compile time, at runtime it will just be a String and the constructor will just be a static method that calls
(That's not quite the whole story - there are times when the compiler has to box the value in a real
instance at runtime - but I can't remember when that happens...)