Search code examples
kotlindata-class

What is the better way to declare fields in data class in Kotlin?


Say I have a data class:

data class Money(private var _amount: Int, private val currency: String) {
    private var amount: Int = _amount
        get() {
            return if (field < 0) 0 else field
        }

    override fun toString(): String {
        return "Money(amount=$amount, currency='$currency')"
    }

}

I want to know what should I pass as a parameter: var or val? Should I add private modification? In which case is the best practice? Because when I add a getter I must change it to var, but as I know, it's always better to write val in Kotlin?


Solution

  • I'd like to write the code you've given like this:

    data class Money(private var _amount: Int, private val currency: String) {
        private var amount: Int
            get() = _amount.coerceAtLeast(0)
            set (value) { _amount = value }
    
        override fun toString() = "Money(amount=$amount, currency='$currency')"
    }
    
    • _amount can be simply a parameter, it shouldn't be a field, it will gone after construction, and it's only accessible in the init block, the constructor and the field variable initializers (imagine a constructor parameter in Java).
    • coerceAtLeast is a useful utility extension in the stdlib
    • methods with only one return statements can be written as one-linear
    • Data classes should be pure data classes, I don't think you should declare a property with backing field.
      • Instead, use a private property as the backing field and mutate the backing field through the getter and the setter which are actually wrappers to the private field.

    A less important thing is, the type of amount can be inferred, but I'd like to explicitly declare it here since it's more friendly for new comers to read.