spasfonx
spasfonx

Reputation: 170

Kotlin - Transform value at initialisation

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

Answers (2)

vi-kun
vi-kun

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

s1m0nw1
s1m0nw1

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

Related Questions