Fluent methods for data class in kotlin

回眸只為那壹抹淺笑 提交于 2019-12-01 13:25:44

If don't need to return anything but Name, you can just do it like this instead:

data class Name(var firstName: String, var lastName: String)

fun foo() {
    val name = ...
    name.apply {
        firstName = ...
        lastName = ...
    }
}

or another example:

CorrutOfficeAccount(....).apply {
    method1()
    addCollectedFee(20000)
    method3()
}

Inside the function (what's inside the curly braces) passed to apply, this is the object apply was called on, which makes it possible to refer to member functions and properties like firstName without writing name.firstName.

If you're not happy with this: It's not possible to make the actual setter return something, however you can of course just define a method with a different name and make that return something.

For accessing properties in Kotlin, we don't use getter and setter functions, and while you can override their setters to give them custom behaviour, you can't make them return anything, because calling them is an assigment, which is not an expression in Kotlin. As an example, this doesn't work:

var x = 1
var y = (x = 5) // "Assigments are not expressions, and only expressions are allowed in this context"

What you can do is define additional methods that set them, and then return the instance they were called on. For example:

data class Name(var firstName: String = "", var lastName: String  =  "") {
    fun withLastName(lastName: String): Name {
        this.lastName = lastName
        return this
    }
}

val name = Name(firstName = "Jane") 
name.withLastName("Doe").withLastName("Carter")

Note that if you name this method setLastName, you'll have problems with using the class from Java, because the lastName property is already visible through a method called setLastName when you're writing Java code.

The perhaps more usual solution in Kotlin though is to replace fluent builders by using apply from the standard library, as it was already described in Christian's answer.

Thanks to Zsmb13 and Christin for the answer, but if someone wants to use immutable fields I have another solution

data class Foo(val fooString: String = "", val fooInt: Int = 0) {
    fun increaseTwo() = copy(fooInt = fooInt + 2)
    fun increaseThree() = copy(fooInt = fooInt + 3)
}

And you can use it like this

println( Foo("foo",2).increaseTwo().increaseThree())

Output :

Foo(fooString=foo, fooInt=7)
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!