Clases enumeradas en Kotlin

video[Tutorial Clases enumeradas en Kotlin

Las clases enumeradas (enum) nos permiten declarar un conjunto de valores que puede tomar una variable:
 

sealed class Figura {
   class Triangulo(val lado1:Int, val lado2:Int, val lado3:Int) : Figu-ra()
   class Cuadrado(val lado:Int) : Figura()
   class Circulo(val radio:Int) : Figura()
} 
Al igual que en Java, un enumerado se define por medio de una clase, aunque ahora es más evidente al tener que indicar class. Cada una de las constantes de un enum supone la creación de un objeto. Por lo que en el ejemplo anterior se crearán cuatro objetos. Una variable de tipo Estaciones no es más que una referencia a uno de estos cuatro objetos. Lo estudiamos con detalle en el siguiente punto. Como cada constante es una instancia de la clase, se pueden inicializar:
enum class VersionAndroid(val api: Int) {
    JELLY_BEAN(16), KITKAT(19), MASHMALLOW(23), NOUGAT(24)
} 
Una constante de un enumerado también puede declarar sus propios métodos y propiedades:
enum class Estacion {
   PRIMAVERA { override fun temperatura() = 24.0 },
   VERANO { override fun temperatura() = 32.2 };
   abstract fun temperatura(): Double
   var diasSoleados: Int = 0
} 
Si un enumerado define algún miembro, este ha de separarse de las constantes con un punto y coma, del mismo modo que hacíamos en Java. Igualmente, las clases enum en Kotlin tienen métodos sintéticos que permiten listar las constantes definidas (values()) y obtener una constante por su nombre (valueOf()). Además, en cada constante se definen las propiedades name y ordinal:
 

Comparativa clases enumeradas y selladas

Las clases selladas se asemejan mucho a las clases enumeradas, pero no son exactamente lo mismo. Las clases selladas son una extensión de las cla-ses enumeradas, ya que el posible conjunto de valores de un tipo enumerado también están restringidos, pero mientras que cada constante del tipo enume-rado solo existe como una única instancia, una subclase de una clase sellada puede tener múltiples instancias.
La forma de implementar un enum es similar a una clase sellada donde to-dos sus elementos son objetos:
enum class Estacion { 
   PRIMAVERA, 
   VERANO, 
   …
} 
sealed class Estacion() {
   object PRIMAVERA: Estacion() 
   object VERANO: Estacion() 
   …
} 
El mejor modo de ver las diferencias es a través de un ejemplo:
enum class Direcciones { ARRIBA, IZQUIERDA, DERECHA, ABAJO }
sealed class Intention {            
   object None : Intention()
   object Refresh : Intention()
   data class Error(val reason: String) : Intention()
   data class LoadContent(val content: List<String>) : Intention()
} 
Ambas tienen el mismo comportamiento que una clase abstracta, evitando una instanciación directa de las mismas, a la vez que nos permiten declarar métodos abstractos:
enum class Direcciones {
   ARRIBA   { override fun direccion(x: Int, y: Int) = x to (y - 1) },
   IZQUIERDA{ override fun direccion(x: Int, y: Int) = (x - 1) to (y) },
   DERECHA  { override fun direccion(x: Int, y: Int) = (x + 1) to (y) },
   ABAJO    { override fun direccion(x: Int, y: Int) = x to (y + 1) };
   abstract fun direccion(x: Int, y: Int): Pair<Int, Int>
}
sealed class Intention {
   object None : Intention() {
      override fun log() { println("none") }
   }
   object Refresh : Intention() {
      override fun log() { println("refresh") }
   }
   data class Error(val reason: String) : Intention() {
      override fun log() { println("error") }
   }
   data class LoadContent(val content: List<String>) : Intention() {
      override fun log() { println("loadContent") }
   }
   abstract fun log()
} 
Por otro lado, una clase enumerada únicamente puede crear una instancia de cada constante, mientras que podremos tener varias instancias de las sub-clases de una clase sellada. Dependiendo de lo que queramos hacer podre-mos utilizar una u otra. Esto es, si necesitamos un comportamiento constante, utilizaremos una clase enumerada y, en caso contrario, una clase sellada.
Preguntas de repaso: Clases selladas y enumeradas