¿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.

  • Igualdad en Kotlin
  • enlace de vista de android.R.id en Kotlin
  • Archivo encontrado en IntelliJ pero no en jar integrado
  • La reference Int :: class.javaPrimitiveType.kotlin no es igual a Int :: class.javaObjectType.kotlin
  • El controller de exception Spring Boot @ControllerAdvice no se activa
  • Advertencia obsoleta de Kotlin Runtime (complemento Kotlin 1.1.2-release-Studio2.3-3)
  • Repetir una alarma para disparar exacta en el momento específico no funciona correctamente
  • advertencia: los files JAR en time de ejecución de Kotlin en el classpath deben tener la misma versión
  • Kotlin - param genérico en list - mezcla de Java y Kotlin
  • La function miembro no se puede usar como argumento
  • Moshi / Kotlin - ¿Cómo serializar cadenas NULL JSON en cadenas vacías?