Cómo imitar o lograr relaciones IS-A para las classs de datos de Kotlin

He estado explorando Kotlin y he escrito un pequeño progtwig / script que hace una tarea que me resulta aburrida.

En el desarrollo del progtwig utilizo classs de datos para representar una list de reproducción. En un punto del layout, quería tener un tipo especial de Playlist que fuera EmptyPlaylist .

No pude hacer que esto funcione.

¿Cómo lograría esta relación con Kotlin?

En Java, simplemente extendería la Playlist (o tal vez crearía una class de interfaz / resumen para que henetworkingen ambos).

Solo quería poder tener una List<Playlist> lugar de List<Playlist?>

Al final, acabo de crear un object Playlist , pero estoy interesado en si es posible crear jerarquías IS-A con classs de datos.

UPD: Kotlin Beta agregó restricciones en data classs de data , por lo que la respuesta también se ha actualizado.

  • Las classs de datos no pueden ser abstractas, abiertas, selladas o internas;
  • Las classs de datos no pueden extender otras classs (pero pueden implementar interfaces).

Entonces, la única opción para build sus jerarquías son las interfaces. Esta restricción puede ser lanzada en futuras versiones.


La idea de henetworkingar EmptyPlaylist de Playlist que se presume no está vacía de acuerdo con tus palabras parece un poco contradictoria, pero hay opciones:

  • Puede hacer que tanto TracksPlaylist como EmptyPlaylist implementen una interfaz Playlist . Esto es razonable porque EmptyPlaylist puede no contener todo lo que hace una Playlist . Esto se vería así:

     public interface Playlist data class TracksPlaylist(val name: String, val tracks: List<Track>) : Playlist data class EmptyPlaylist(val name: String): Playlist 
  • Si no quiere que incluso existan varias instancias de EmptyPlaylist , puede convertirlo en val lugar de en class distinta y evitar is-checks, simplemente comparando con

     val EMPTY_PLAYLIST = TracksPlaylist("EMPTY", listOf()) 

    Esto es aplicable cuando las lists de reproducción vacías son todas iguales, por lo que un solo object es suficiente para representarlas todas.

  • Puedes usar classs sealed . Esto no le permite usar classs de data , pero las classs sealed pueden ajustarse para build jerarquías de classs como esta.

    class sealed es una class abstracta que solo puede tener sus subclasss declaradas dentro de su cuerpo. Esto le da al comstackdor garantías de que estas son las únicas subclasss. Ejemplo:

     sealed class Playlist(val name: String) { class Tracks(name: String, val tracks: List<Track>): Playlist(name) class Playlists(name: String, val innerPlaylists: List<Playlist>): Playlist(name) object Empty: Playlist("EMPTY") } 

    Después de eso, podrá usar la instrucción when sin especificar la twig else si declara todas las subclasss y objects de la class sellada:

     when (p) { is Playlist.Tracks -> { /* ... */ } is Playlist.Playlists -> { /* ... */ } Playlist.Empty -> { /* ... */ } } 

    Sin embargo, esta opción requiere que se ocupe de equals , hashCode , toString , copy y componentN por su count, si los necesita.

  • No se puede usar getter personalizado con propiedad delegada
  • Herencias internas Herencia en Kotlin
  • Cómo pasar los valores de actividad a otra actividad en kotlin
  • Extensiones Kotlin references no resueltas
  • Cómo get un package de kotlin por reflexión
  • romper o regresar de cuando expresiones
  • Dibuja una línea en el canvas lentamente como una animation
  • Asignación de properties a un object javascript utilizando nombres de properties dinámicas
  • Recolectando artículos con las transmisiones de Kotlin
  • Ninguno de los siguientes candidatos es responsable debido a la falta de coincidencia del tipo de receptor
  • Kotlin loop con pasos irregulares