Por favor, eche un vistazo al código siguiente, donde Extractor[A,B]
es parte de un marco genérico y todo lo demás debe considerarse como "código de cliente" (hermé un poco y renombrado todo. Así que no importa que Extractor
no parezca demasiado útil).Herencia y conversión de tipo automático?
scala> abstract class Extractor[A,B] {
| def extract(d:A):B
| def stringRepr(d:A):String
| }
defined class Extractor
scala> sealed abstract class Value
defined class Value
scala> case class IntValue(i:Int) extends Value
defined class IntValue
scala> case class StringValue(s:String) extends Value
defined class StringValue
scala> case class Data(i:Int, s:String)
defined class Data
scala> sealed abstract class MyExtractor[Value] extends Extractor[Data, Value] {
| def stringRepr(d:Data) = extract(d) match {
| case IntValue(i) => i.toString
| case StringValue(s) => s
| }
| }
defined class MyExtractor
scala> class IntExtractor(name:String) extends MyExtractor[IntValue] {
| def extract(d:Data) = IntValue(d.i)
| }
defined class IntExtractor
scala> class StringExtractor(name:String) extends MyExtractor[StringValue] {
| def extract(d:Data) = StringValue(d.s)
| }
defined class StringExtractor
por lo que en palabras cortas Extractor[A,B]
se utiliza para extraer algún valor B
de A
y hacer algunas otras cosas que no están representados en este código espectáculo. Las clases abstractas Value
y MyExtractor
se utilizan por razones de tipo savety en el "código de cliente". Cuando intento crear un List
de MyExtractor
s, ocurre lo siguiente:
scala> val l = List.empty[MyExtractor[Value]]
l: List[MyExtractor[Value]] = List()
scala> new IntExtractor("test1") :: l
res5: List[MyExtractor[_ >: IntValue <: Value]] = List([email protected])
tratando de convertir un IntExractor
a una superclase
scala> new IntExtractor("test"):MyExtractor[Value]
<console>:24: error: type mismatch;
found : IntExtractor
required: MyExtractor[Value]
new IntExtractor("test"):MyExtractor[Value]
^
scala> new IntExtractor("test"):Extractor[Data,Value]
<console>:24: error: type mismatch;
found : IntExtractor
required: Extractor[Data,Value]
new IntExtractor("test"):Extractor[Data,Value]
Soy consciente de que todo está bien, cuando me defino IntExtractor
como este
scala> class IntExtractor(name:String) extends MyExtractor[Value] {
| def extract(d:Data) = IntValue(d.i)
| }
defined class IntExtractor
scala> new IntExtractor("test"):Extractor[Data,Value]
res17: Extractor[Data,Value] = [email protected]
Pero no entiendo, ¿por qué no funciona de la manera en que lo intenté arriba. Les agradecería cualquier ayuda o sugerencia.
Como regla general, es útil no utilizar los nombres de las clases reales para los parámetros de tipo. Por ejemplo, en 'class MyExtractor [Value]' the 'Value' es un parámetro de tipo y no tiene nada que ver con su' class Value'. Este uso de los nombres tiende a ser confuso para los humanos, aunque por supuesto nunca desconcierta al compilador. –
Su 'Extractor [A, B]' se comporta como 'A => B' (es decir, 'Función1'). Tenga en cuenta que 'Function1' es covariante en su tipo de retorno; se declara como' Function1 [-A, + B] ' –
@ Randall Schulz: No estoy 100% seguro. Lo entiendo bien, pero el' Value' in 'clase MyExtractor [Value] 'SÍ corresponde con la' clase Value'. Por ejemplo, solo estoy buscando subclases de 'Value' en' stringRepr (d: Value): String' – Agl