Шаблон строителя в Котлине

Я новичок в мире котлин. У меня есть существующий строитель, написанный на Java, и хотел бы преобразовать его в Kotlin, поскольку я переношу проект на kotlin в Android. Тем не менее, встроенный в Android Studio инструмент имеет некоторые ошибки, а затем преобразованный код не компилируется. Он недоступен для переменных в моем классе UserBuilder .

Вот код Java из учебника

 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); } } } 

Автоматически преобразованный код kotlin:

 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) } } } 

ОБНОВЛЕНО

 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) } } } 

Учитывая, что это Kotlin, вы можете сделать это намного проще, используя класс данных.

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

Вот и все! Первые два параметра требуются, но если вы хотите указать больше, вы просто укажете их по имени:

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

Никакой строитель не нужен!

Просто делайте простое преобразование, как и раньше.

Теперь вы увидите, что UserBuilder будет иметь модификатор internal доступа, просто удалите его и добавьте публикацию или что бы вы ни UserBuilder .


Edit1

Хорошо, internal ключевого слова нет в вашем коде Kotlin , я не обратил внимания на это, проверяя ваш код.

Итак, теперь вам нужно создать объект в классе Person и разместить там свой класс UserBuilder .

Проверьте следующий код:

 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) } } } } 

Это должно работать как в вашем Java-коде.

Надеюсь, поможет.

 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) } } 

}

Использование пользовательских геттеров таким образом может решить проблему с частным доступом.