¿Cuál es la forma correcta de tratar con los campos en Kotlin?

¿Cómo debo manejar la migration de una class Java con campos a Kotlin correctamente?

Un par de lecturas en los documentos de Kotlin revelan que sus classs no pueden tener campos definidos dentro de ellas. Siendo el rebelde que soy, en realidad tratando de convertir mi código Java existente a su homólogo Kotlin (utilizando la function de convertidor Java to Kotlin de Android Studio) también marca "campos" con un resaltado desagradablemente cegador .

Esta es mi class de Java:

public final class PaperDay implements Day { private Date date; private Weather weather; PaperDay() { // Obligatory empty ctor for Paper. } PaperDay(Date date) { this.date = truncateTimeFromDate(date); this.weather = Weather.SUNNY; // Default to SUNNY, 'cos sunny is good! } PaperDay(Date date, Weather weather) { this.date = truncateTimeFromDate(date); this.weather = weather; } private Date truncateTimeFromDate(Date date) { Calendar calendar = Calendar.getInstance(); calendar.setTime(date); calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.set(Calendar.MINUTE, 0); ... 

..y esto es lo que parece convertido a .kt:

enter image description here

¿Cómo puedo hacer esto de la manera Kotlin?

Supongo que quieres algo como esto:

 class PaperDay (private var date: Date, private var weather: Weather = Weather.SUNNY) : Day { init { this.date = truncate(date) } private fun truncateTimeFromDate(date1: Date): Date { return date1 } } 

Deberías intentar usar parameters opcionales ( var weather: Weather = Weather.SUNNY ) siempre que puedas, ya que aumentan mucho la legibilidad.

Para evitar el bloque init (algo feo) también puede pasar solo una de las dos properties como parámetro constructor (gracias a Jayson Minard), y calcular la otra propiedad en su statement usando un parámetro "normal":

 class PaperDay (dateWithTime: Date, private val weather: Weather = Weather.SUNNY): Day { private val date: Date = truncateTimeFromDate(dateWithTime) ... } 

Tenga en count que esto también está utilizando val lugar de var ya que la inmutabilidad suele ser la mejor opción.

Si necesita tener el constructor vacío también, puede agregarlo (aunque no creo que sea una buena práctica y es un indicador del layout "malo":

  constructor() : this(Date()) 

Alternativamente, agregar un valor pnetworkingeterminado para todos los parameters en el constructor creará implícitamente un constructor vacío también.

si realmente desea la nulabilidad, defina sus properties usando ? . P.ej:

 class PaperDay (private var date: Date?, private var weather: Weather? = Weather.SUNNY) 

también puede cambiar el otro constructor a constructor() : this(null)


Además, en mi humilde opinión también es una buena idea agregar el método truncate... como una function de extensión para la class Date en lugar de uploadlo en esta class:

 fun Date.truncateTimeFromDate() { Calendar calendar = Calendar.getInstance() calendar.setTime(this) calendar.set(Calendar.HOUR_OF_DAY, 0) calendar.set(Calendar.MINUTE, 0) ... } 

Similar a @Lovis pero evitando el uso de var que debería ser un "último recurso":

 class PaperDay (dateWithTime: Date = Date(), private val weather: Weather = Weather.SUNNY): Day { private val date: Date = truncateTimeFromDate(dateWithTime) private fun truncateTimeFromDate(dateWithTime : Date) : Date { ... } } 

En esta versión, el constructor tiene un parámetro que no es una propiedad de class, y el otro es una propiedad. Más adelante en el cuerpo de la class, la propiedad se declara y se establece en la date truncada.

Si tiene un valor pnetworkingeterminado para cada parámetro de constructor, Kotlin creará automáticamente un constructor pnetworkingeterminado que use esos valores pnetworkingeterminados. No es necesario agregarlo por separado.

Si su infraestructura debe instanciar con el constructor pnetworkingeterminado y luego establecer los valores después del hecho, querrá hacer algo más como el siguiente y volver a usar var :

 class PaperDay (dateWithTime: Date = Date(), private var weather: Weather = Weather.SUNNY): Day { private var date: Date = truncateTimeFromDate(dateWithTime) set(value) { field = truncateTimeFromDate(value) } private fun truncateTimeFromDate(dateWithTime : Date) : Date { return dateWithTime } } 

Ahora nos hemos asegurado de que nunca tengamos una date inválida almacenada en la propiedad al tener un setter personalizado.

Si desea interoperabilidad para todas las variaciones del constructor disponible desde Java, puede usar la anotación @JvmOverloads en el constructor para generar otras permutaciones de uso de valores de parameters pnetworkingeterminados.

Y como señala @Lovis, mueva truncateTimeFromDate a una function de extensión en la class Date . Puede ser local para el file, para el module, para la class, y en todos esos casos se leerá mejor.

  • Kotlin anula el comportamiento val abstracto, object vs class
  • Extender apropiadamente una class de Widget usando Kotlin
  • ¿Podemos usar infix methods generics en Kotlin?
  • Controles de pelusa de Kotlin y Android
  • ¿Cómo puedo convertir CharArray / Array <Char> en una cadena?
  • Implementando la interfaz Java - Kotlin
  • Advertencia obsoleta de Kotlin Runtime (complemento Kotlin 1.1.2-release-Studio2.3-3)
  • Obtener el porcentaje de orientación en píxeles mediante progtwigción
  • Android WebView salta a la cima en cada actualización de página (?)
  • Obtener class acompañante en un object complementario
  • Kotlin equivalente a Groovy spead-dot (*.)