Kotlin admite propiedades calculadas, pero no estoy seguro de cuándo usarlas.
Digamos que tengo una clase:
class Car(val color: String) y tener esta función que devuelve true si el auto es blanco:
fun isWhite(car: Car): Boolean { return car.color == "WHITE" }Ahora quiero que esta función sea una función miembro (un método ); esto se vería así:
class Car(val color: String) { fun isWhite(): Boolean = color == "WHITE" }pero también puede verse así:
class Car(val color: String) { val isWhite: Boolean get() = color == "WHITE" }¿Entonces cual es mejor?
Las convenciones de codificación oficiales de Kotlin definen en la sección Funciones frente a propiedades lo siguiente:
En algunos casos, las funciones sin argumentos pueden ser intercambiables con propiedades de solo lectura. Aunque la semántica es similar, existen algunas convenciones estilísticas sobre cuándo preferir uno u otro.
Prefiere una propiedad sobre una función cuando el algoritmo subyacente:
- no tira
- es barato de calcular (o se almacena en caché en la primera ejecución)
- devuelve el mismo resultado sobre las invocaciones si el estado del objeto no ha cambiado
Entonces, usaría en el ejemplo anterior un val para isWhite , ya que no arroja, la comparación de cadenas es económica de calcular y el color del Car no puede cambiar, ya que Car.color se define como val .
Tenga en cuenta que el código de bytes de JVM del bloque get() se compilará exactamente con el mismo código que tendría la función. Por lo tanto, ambos enfoques son iguales con respecto al código de bytes compilado y no hay diferencia de rendimiento .
Para agregar a otras respuestas, estas son del libro Java a Kotlin , capítulo 11 Métodos a Propiedades :
Supongamos que queremos agregar edad a esta clase:
data class Person(val dateOfBirth: LocalDate) Podemos calcular la edad fácilmente (ignorando las zonas horarias) a partir de la propiedad dateOfBirth . Pero esto no depende solo de esa propiedad; también depende de cuando lo llamemos.
Aunque es poco probable, fred.age == fred.age puede devolver false .
La edad es una acción ; su resultado depende de cuándo se llame. Las propiedades deben ser cálculos , atemporales y dependientes solo de sus entradas, en este caso, la propiedad dateOfBirth .
Por lo tanto, age() debería ser una función, no una propiedad:
data class Person(val dateOfBirth: LocalDate) { fun age() = Period.between(dateOfBirth, LocalDate.now()).years } ¿Qué pasa si queremos un hash criptográfico de todas las demás propiedades del objeto? Este es un cálculo (para objetos inmutables), pero si es costoso de calcular, debería ser un método hash() no un hash de propiedad. Incluso podríamos querer insinuar el costo del método en su nombre:
data class PersonWithProperties( val givenName: String, val familyName: String, val dateOfBirth: LocalDate ) { fun computeHash(): ByteArray = someSlowHashOf(givenName, familyName, dateOfBirth.toString()) }Preferencia personal.
Mi opinión sería, si no necesita pasar nada, créelo como una propiedad.
Pero si necesitas pasarle más información, ¡tendrá que ser una función!