Builder template in Kotlin

I am new to the world of kotlin. I have an existing builder written in Java and would like to convert it to Kotlin since I am transferring the project to kotlin in Android. However, the built-in tool in Android Studio has some errors, and then the converted code does not compile. It is not available for variables in my UserBuilder class.

Here is the java code from the 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); } } } 

Automatically 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) } } } 
+5
source share
3 answers

Given this Kotlin, you can make it a lot easier using the data class.

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

And this! The first two parameters are required, but if you want to specify more, you simply specify them by name:

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

No builder needed!

+5
source

Just do a simple conversion as you did before.

Now you will see that UserBuilder will have an internal access modifier, just delete it and add a publication or something else that you need.


Edit1

Well, the internal keyword is missing in your Kotlin code, I didn’t notice that when checking the code.

So now you need to create an object in the Person class and put the UserBuilder class in it.

Check out the following code:

 class Person private constructor(builder: 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 } object Builder { 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) } } } } 

This should work as in your Java code.

Hope this helps.

0
source
 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(private val _firstName: String, private val _lastName: String) { private var _age: Int = 0 private var _phone: String? = null private var _address: String? = null var firstName: String get() = this._firstName var lastName: String get() = this._lastName var age: Int = 0 get() = this._age var phone: String? = null get() = this._phone var address: String? = null get() = this._address 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) } } 

}

Using custom getters in this way can solve the problem of the private access modifier.

0
source

Source: https://habr.com/ru/post/1270726/


All Articles