Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fluent methods for data class in kotlin

We are familiar with fluent interfaces for calling methods in java and other programming languages. For eg:

Picasso.with(this).load(url).into(imageView);

This is made possible by setter methods what return object of desired type.

public Picasso with(Context context)
{
    this.context = context;
    return this;
}

public X load(String url)
{
    this.url = url;
    return this;
}

public Y load(ImageView imageView)
{
    this.imageView = imageView;
    return this;
}

I am trying to do the same with kotlin data classes but sadly I could not find a way to override the setter methods in which I could return the new instance of that object.

I get compiler error when I try to forcefully override setter method. enter image description here

Any idea about what can be done so that I can call fluent interfaces or at least alter how the setter works may be like this

data class CorruptOfficeAccount(.....){
     override fun addCollectedFee(Long money) :CorruptOfficeAccount {
     this.money = money/5
    }
}

So that I can call

CorrutOfficeAccount(....).method1().addCollectedFee(20000).method3()
like image 234
erluxman Avatar asked May 21 '17 14:05

erluxman


People also ask

Can data class have methods?

A data class refers to a class that contains only fields and crude methods for accessing them (getters and setters). These are simply containers for data used by other classes. These classes don't contain any additional functionality and can't independently operate on the data that they own.

How do you write a data class in Kotlin?

Android Dependency Injection using Dagger with KotlinThe primary constructor needs to have at least one parameter. All primary constructor parameters need to be marked as val or var. Data classes cannot be abstract, open, sealed, or inner. The class may extend other classes or implement interfaces.

When should I use data class Kotlin?

Answer: Kotlin provides a special type of class called data class, which is usually used for objects that act as a store for data properties and has no business logic or member functions. It provides a lot of advantages with reduced boilerplate code.


2 Answers

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.

like image 62
Christian Brüggemann Avatar answered Sep 19 '22 12:09

Christian Brüggemann


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.

like image 40
zsmb13 Avatar answered Sep 22 '22 12:09

zsmb13