Reputation: 170
i'm new in kotlin and i want to know if we can transform a content value at initialisation : with this example :
@Document
data class Category(
@Id val id: Id? = null,
val label: String
)
Category is a document (entity for mongodb) and when i'm instanciating this object, i want to transform label property in uppercase. How can i do that to stay idiomatic with the language ? The point is to keep the immutable properties of the val
keyword.
val categ = Category(label = "Test")
println(categ.label) // --> TEST
Thanks.
Upvotes: 1
Views: 987
Reputation: 53
Adding to s1m0nw1's solution, an alternative approach may be to use a private primary constructor and a secondary public constructor, which functions the same but has a slightly different signature to avoid conflict. This can be particularly useful when a public constructor is necessary. Below is an implementation example for your specific case:
@Document
data class Category private constructor(
@Id val id: Id?,
val label: String,
) {
constructor(
id: Id? = null,
label: CharSequence,
) : this(id, label.toString().uppercase())
}
This approach also works for value classes. However, do note that both this solution and the one by s1m0nw1 can be bypassed by the copy()
method generated for data classes.
Upvotes: 1
Reputation: 81929
You can encapsulate the "upperCasing" into a factory:
data class Category constructor(val label: String) {
init {
if (label != label.toUpperCase()) {
throw IllegalStateException("Label must be uppercase")
}
}
companion object {
fun createInstance(str: String) = Category(str.toUpperCase())
}
}
The init
block ensures, that clients don't create unwanted instances with non-upper labels (which should be documented).
Create an instance like this:
val instance = Category.createInstance("xy")
You might want to make explicit that you do transformations if the parameter is not upper case already by naming the factory accordingly, e.g. withTransformedLabel
or simply add some documentation ;-)
Upvotes: 2