Patrón de constructor en Kotlin

Soy nuevo en el mundo de Kotlin. Tengo un constructor existente escrito en Java y me gustaría convertirlo a Kotlin ya que estoy migrando el proyecto a Kotlin en Android. Sin embargo, la herramienta incorporada de Android Studio parece tener algunos errores, y luego el código convertido no es comstackble. Se muestra inaccesible para las variables en mi class UserBuilder .

Aquí está el código de Java del tutorial

 public class Person { private final String firstName; // requinetworking private final String lastName; // requinetworking 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); } } } 

El código de kotlin convertido automáticamente:

 class Person private constructor(builder: UserBuilder) { val firstName: String // requinetworking val lastName: String // requinetworking 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) } } } 

ACTUALIZADO

 class Person private constructor(builder: UserBuilder) { val firstName: String // requinetworking val lastName: String // requinetworking 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) } } } 

Dado que es Kotlin, en realidad puede simplificar esto usando una class de datos.

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

¡Y eso es! Los dos primeros parameters son obligatorios, pero si desea especificar más, simplemente especifíquelos por nombre:

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

¡No se necesita constructor!

Simplemente haga una conversión simple como lo hizo antes.

Ahora verá que UserBuilder tendrá internal modificador de acceso internal simplemente elimínelo y agregue public o cualquiera que sea su requerimiento.


Edit1

Ok, internal palabra key internal no está en tu código de Kotlin , pasé por alto eso mientras revisaba tu código.

Entonces, lo que tienes que hacer es crear un object en la class Person y poner tu class UserBuilder allí.

Verifique el siguiente código:

 class Person private constructor(builder: Builder.UserBuilder) { val firstName: String // requinetworking val lastName: String // requinetworking 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) } } } } 

Esto debería funcionar como en tu código de Java.

Espero eso ayude.

 class Person private constructor(builder: UserBuilder) { val firstName: String // requinetworking val lastName: String // requinetworking 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) } } 

}

El uso de captadores personalizados de esta forma puede resolver el problema del modificador de acceso privado.

  • Función genérica de extensión de Kotlin con types básicos sin API de reflexión
  • señal 7 (SIGBUS), código 2 (BUS_ADRERR)
  • TestScheduler no funciona (Kotlin + RxJava2 + mockito)
  • Runnable no se ejecuta en la barra de acción flotante en Android
  • Acceda a las classs Apollo generadas desde el package secundario - Kotlin
  • La aplicación se bloquea al girar la pantalla
  • Jackson Mixins con Kotlin
  • ¿Cómo dividir una cadena con un set de delimitadores y encontrar qué delimitador era? Kotlin
  • Obtenga un hilo extra de la actividad de Kotlin
  • cómo controlar el flujo de datos cuando se usa correctamente en kotlin
  • Kotlin Android Firebase Database Hashmap lanzado a la class