In a data class can you have properties other than those generated automatically?

5

Kotlin allows you to simplify the creation of what we call POJO in Java:

data class Person(val firstName: String, val lastName: String)

We get a class with the getter for all variables declared in the constructor as well as the methods equals() , toString() , copy() , among others.

My question is whether you can add other properties. For example in class Person add / declare property fullName: String .

    
asked by anonymous 11.08.2017 / 20:00

3 answers

2

It is possible to create extensions of property, and in the example cited it should work because I believe that the background is not a property, to tell you the truth, I do not really like the name, because I think that property implies having a linked state field , which is not very much the case. Then you can create a getter method and even a setter depending on what you want to do and the usage syntax will be the same as a field, but can not have an associated status field , then the answer is yes to the behavior and not to the state.

It is possible to add behaviors and even extra states in data class itself, but they will not be part of the basic structure of the class, for example a property that is not in the primary constructor does not enter equals() , or toString() .

fun main(args: Array<String>) {
    val pessoa = Person("João", "Silva")
    pessoa.age = 47
    println(pessoa.fullName)
    println(pessoa.Firula())
    println(pessoa.firula)
    val pessoa2 = pessoa.copy()
    println(pessoa2.age)
    pessoa2.age = 40
    println(pessoa2.age)
    println(pessoa == pessoa2)
    println(pessoa2)
}

data class Person(val firstName: String, val lastName: String) {
    fun Firula(): String = "O nome dele é " + firstName + " " + lastName
    val firula: String
        get() = "O nome dele é " + firstName + " " + lastName
    var age: Int = 0
    override fun toString() = firstName + " " + lastName
}

val Person.fullName: String
    get() = firstName + " " + lastName

See running on ideone . And no Coding Ground . Also I put it in GitHub for future reference .

Of course it is possible to extend with functions as well that only behaves.

Just notice that the extension occurs statically, there is no inheritance in this extension. Then they are only facilitators, it does not change the class structure, either a data class or a normal class.

    
11.08.2017 / 20:42
4

Yes, it is possible. One way to do this is through extensions .

You can create both functions and properties in this way.

To declare an extension, you must prefix your name with the type being extended.

The keyword this is valid within extension functions and is used to refer to the "recipient" object (which is extended). >

Extension properties do not support the use of backing fields .

See a complete example

fun main(args: Array<String>) {
    val per = Person("Linq", "Bueno")
    println(per.obterFullName())
    println(per.fullName)
}

fun Person.obterFullName() = "${this.firstName} ${this.lastName}"
// ^ Isto é uma função de extensão

val Person.fullName: String
  get() = "${this.firstName} ${this.lastName}"
// ^ Isto é uma propriedade de extensão    

data class Person(val firstName: String, val lastName: String)

See it working here.

    
11.08.2017 / 20:28
2

Complementing the excellent answers, you can create immutable properties based on existing ones.

Be at startup / declaration:

data class Person(val firstName: String, val lastName: String) {
    val fullName = "$firstName $lastName"
}

If it still makes more sense because of organization (of course, if the startup is small we do not need to use init ):

data class Person(val firstName: String, val lastName: String) {
    val fullName: String

    init {
        fullName = "$firstName $lastName"
    }
}

Or via lazy instantiation:

data class Person(val firstName: String, val lastName: String) {
    val fullName: String by lazy { "$firstName $lastName" }
}
    
11.08.2017 / 22:03