Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Builder Pattern in Kotlin

Tags:

kotlin

I am new to kotlin world. I have a existing builder written in Java and would like to convert it to Kotlin as I am migration the project to kotlin in Android. However, the Android Studio built-in tool seems have some bugs, then converted code is not compilable. It is showing inaccessible to the variables in my UserBuilder class.

Here is the Java code from tutorial

public class Person {
    private final String firstName; // required
    private final String lastName; // required
    private final int age; // optional
    private final String phone; // optional
    private final String address; // optional

    private Person(UserBuilder builder) {
        this.firstName = builder.firstName;
        this.lastName = builder.lastName;
        this.age = builder.age;
        this.phone = builder.phone;
        this.address = builder.address;
    }

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public int getAge() {
        return age;
    }

    public String getPhone() {
        return phone;
    }

    public String getAddress() {
        return address;
    }

    public static class UserBuilder {
        private final String firstName;
        private final String lastName;
        private int age;
        private String phone;
        private String address;

        public UserBuilder(String firstName, String lastName) {
            this.firstName = firstName;
            this.lastName = lastName;
        }

        public UserBuilder age(int age) {
            this.age = age;
            return this;
        }

        public UserBuilder phone(String phone) {
            this.phone = phone;
            return this;
        }

        public UserBuilder address(String address) {
            this.address = address;
            return this;
        }

        public Person build() {
            return new Person(this);
        }

    }
}

The auto converted kotlin code:

class Person private constructor(builder: UserBuilder) {
    val firstName: String // required
    val lastName: String // required
    val age: Int // optional
    val phone: String // optional
    val address: String // optional

    init {
        //cannot access the variables, they are private in UserBuilder
        this.firstName = builder.firstName  
        this.lastName = builder.lastName   
        this.age = builder.age
        this.phone = builder.phone
        this.address = builder.address
    }

    class UserBuilder(private val firstName: String, private val lastName: String) {
        private var age: Int = 0
        private var phone: String? = null
        private var address: String? = null

        fun age(age: Int): UserBuilder {
            this.age = age
            return this
        }

        fun phone(phone: String): UserBuilder {
            this.phone = phone
            return this
        }

        fun address(address: String): UserBuilder {
            this.address = address
            return this
        }

        fun build(): Person {
            return Person(this)
        }

    }
}

UPDATED

class Person private constructor(builder: UserBuilder) {
    val firstName: String // required
    val lastName: String // required
    val age: Int // optional
    val phone: String? // optional
    val address: String? // optional

    init {
        this.firstName = builder.firstName
        this.lastName = builder.lastName
        this.age = builder.age
        this.phone = builder.phone
        this.address = builder.address
    }

    class UserBuilder(internal val firstName: String, internal val lastName: String) {
        internal var age: Int = 0
        internal var phone: String? = null
        internal var address: String? = null

        fun age(age: Int): UserBuilder {
            this.age = age
            return this
        }

        fun phone(phone: String): UserBuilder {
            this.phone = phone
            return this
        }

        fun address(address: String): UserBuilder {
            this.address = address
            return this
        }

        fun build(): Person {
            return Person(this)
        }

    }
}
like image 624
IHC_Applroid Avatar asked Aug 10 '17 04:08

IHC_Applroid


People also ask

What is builder pattern in Kotlin?

A builder pattern provides an API to construct an object step- by-step. Builder patterns are particularly useful when objects need to be created dynamically.

Is builder pattern useful in Kotlin?

For most use cases you don't need a Builder pattern in Kotlin and are fine just using a constructor with named arguments and default parameters. In case you have a complex object and/or have a stateful configuration that you want to pass around until you have build the complete object, a Builder is useful.

What is a builder class in Kotlin?

Introduction to Kotlin Builder Pattern. Kotlin builder pattern is used to handle object building which contains lots of parameters, and at the time of making the mutable object, then we are constructing it, which was often used but rarely creating our own.

What is builder pattern in Android?

Builder pattern aims to “Separate the construction of a complex object from its representation so that the same construction process can create different representations.” It is used to construct a complex object step by step and the final step will return the object.


1 Answers

Given it's Kotlin, you can actually make this far simpler using a data class.

data class User(val firstName: String, 
        val lastName: String,
        val age: Int = 0,
        val phone: String? = null,
        val address: String? = null)

And that's it! The first two parameters are required, but if you want to specify more, you just specify them by name:

val user = User("John", "Doe", phone = "555-1212")

No builder needed!

like image 164
Kevin Coppock Avatar answered Sep 21 '22 08:09

Kevin Coppock