En Scala, podemos usar al menos dos métodos para actualizar tipos nuevos o existentes. Supongamos que queremos expresar que algo se puede cuantificar usando un Int
. Podemos definir el siguiente rasgo.
Conversión implícita
trait Quantifiable{ def quantify: Int }
Y luego podemos usar conversiones implícitas para cuantificar, por ejemplo, cadenas y listas.
implicit def string2quant(s: String) = new Quantifiable{
def quantify = s.size
}
implicit def list2quantifiable[A](l: List[A]) = new Quantifiable{
val quantify = l.size
}
Después de importarlos, podemos llamar al método quantify
en cadenas y listas. Tenga en cuenta que la lista cuantificable almacena su longitud, por lo que evita el costoso recorrido de la lista en llamadas posteriores a quantify
.
Clases de tipo
Una alternativa es definir un "testigo" Quantified[A]
que declare que algún tipo A
puede cuantificarse.
trait Quantified[A] { def quantify(a: A): Int }
Luego proporcionamos instancias de esta clase de tipo para String
y en List
algún lugar.
implicit val stringQuantifiable = new Quantified[String] {
def quantify(s: String) = s.size
}
Y si luego escribimos un método que necesita cuantificar sus argumentos, escribimos:
def sumQuantities[A](as: List[A])(implicit ev: Quantified[A]) =
as.map(ev.quantify).sum
O usando la sintaxis ligada al contexto:
def sumQuantities[A: Quantified](as: List[A]) =
as.map(implicitly[Quantified[A]].quantify).sum
Pero, ¿cuándo usar qué método?
Ahora viene la pregunta. ¿Cómo puedo decidir entre esos dos conceptos?
Lo que he notado hasta ahora.
clases de tipo
- las clases de tipos permiten la agradable sintaxis vinculada al contexto
- con clases de tipo, no creo un nuevo objeto contenedor en cada uso
- la sintaxis ligada al contexto ya no funciona si la clase de tipo tiene varios parámetros de tipo; imagina que quiero cuantificar cosas no solo con números enteros sino con valores de algún tipo general
T
. Me gustaría crear una clase de tipoQuantified[A,T]
conversión implícita
- como creo un nuevo objeto, puedo almacenar valores en caché allí o calcular una mejor representación; pero ¿debo evitar esto, ya que podría suceder varias veces y una conversión explícita probablemente se invocaría solo una vez?
Lo que espero de una respuesta
Presente uno (o más) casos de uso en los que la diferencia entre ambos conceptos sea importante y explique por qué preferiría uno sobre el otro. También sería bueno explicar la esencia de los dos conceptos y su relación entre sí, incluso sin ejemplo.