Пожалуйста, взгляните на следующий код, где Extractor[A,B]
является частью общей структуры, а все остальное следует рассматривать как «код клиента» (я немного сварил его и переименовал все, так что не против, что Extractor
не кажется слишком полезным).Преобразование типа наследования и (автоматический?)
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
так и в коротких словах Extractor[A,B]
используется для извлечения некоторого значения B
из A
и сделать некоторые другие вещи, которые не представлены в этом шоу кода. Абстрактные классы Value
и MyExtractor
используются по причинам типа savety в «клиентском коде». Когда я пытаюсь создать List
из MyExtractor
с, происходит следующее:
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])
пытается преобразовать IntExractor
в суперкласса
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]
Я знаю, что все в порядке, когда я определяю IntExtractor
например
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]
Но я не понимаю, почему это не работает так, как я попробовал это выше. Я был бы благодарен за любую помощь или подсказки.
Как правило, полезно использовать имена фактических классов для параметров типа. Например, в 'class MyExtractor [Value]' 'Value' является параметром типа и не имеет ничего общего с вашим значением класса. Это использование имен, как правило, путается с людьми, хотя, конечно, это никогда не ослабит компилятор. –
Ваш 'Extractor [A, B]' ведет себя как 'A => B' (т. Е.' Function1'). Обратите внимание, что 'Function1' является ковариантным в своем возвращаемом типе - он объявлен как' Function1 [-A, + B] ' –
@ Randall Schulz: я не 100% shure Я понимаю вас прав, но класс' Value' в 'классе MyExtractor [Value] 'Соответствует« Value класса ». Например, я проверяю только подклассы 'Value' в' stringRepr (d: Value): String' – Agl