简体   繁体   English

Scala类型系统和继承

[英]Scala type system and inheritance

Take the following Scala code: 采取以下Scala代码:

import scala.collection.mutable.HashMap

class father[T,K:Numeric] extends HashMap[T,K]
class sonA[T] extends father[T, Long]
class sonB[T] extends father[T, Double]

def func_sonA[T](x: List[T]) = {
    // code
    new sonA[T]
}

def func_sonB[T](x: List[T]) = {
    // code
    new sonB[T]
}

val strList = List("one", "two", "three", "four")
val intList = List(1,2,3,4)
val both:List[List[Any]] = List(strList, intList)

val mapped = both.map(x =>
    x match {
        case i:List[String] => func_sonA(i)
        case i:List[Int] => func_sonB(i)
    }
)

The type for mapped is: List[father[_ >: String with Int, _ >: Long with Double : AnyVal]] . mapped的类型为: List[father[_ >: String with Int, _ >: Long with Double : AnyVal]]

What exactly does _>: means? _>:到底是什么意思?

What's the idea behind String with Int and what is it good for? String with Int背后的想法是什么,它有什么用? Seems that it can grow indefinitely ( String with Int with Double With Long with... ). 似乎它可以无限期地增长( String with Int with Double With Long with... )。

How can I specify the type of mapped to be just List[father] or List[father[Any, Any]] without losing the type information? 如何在不丢失类型信息的情况下将mapped的类型指定为List[father]List[father[Any, Any]]

I'm having a bit of a difficulty finding answers since search results for phrases _>: aren't very relevant. 我很难找到答案,因为短语_>:搜索结果不是很相关。


EDIT: 编辑:

To illustrate the actual problem its causing, I want to use a function with a List[father[Any, Any]] input but I can't pass mapped . 为了说明造成此问题的实际问题,我想使用带有List[father[Any, Any]]输入的函数,但无法传递mapped I'm getting a type mismatch error. 我收到类型不匹配错误。

Function: 功能:

def bar(x: List[father[Any, Any]]) = {
    println(x)
}
bar(mapped)

Error: 错误:

Error:(52, 9) type mismatch;
 found   : List[father[_ >: String with Int, _ >: Long with Double <: AnyVal]]
 required: List[father[Any,Any]]
    bar(mapped)
        ^

_ >: String with Int basically means, that the type is either String OR Int . _ >: String with Int基本上意味着该类型是StringInt In case of List[String] you get back a sonA[String] and therefore a father[String, Long] , in case of List[Int] respectively a sonB[Int] and therefore a father[Int,Double] so you end up with a father where the first type is either String or Int and the second type is either Long or Double . List[String]情况下,您会得到一个sonA[String] ,因此在此情况下会返回一个father[String, Long] ;在List[Int]情况下,您将分别sonB[Int]和一个father[Int,Double]所以与father在一起, father的第一种类型为StringInt ,第二种类型为LongDouble

Regarding your other question: 关于其他问题:

How can I specify the type of mapped to be just List[father] or List[father[Any, Any]] without losing the type information? 如何在不丢失类型信息的情况下将映射的类型指定为List[father]List[father[Any, Any]]

Why do you want that? 你为什么要那样? The current type is actually more specific than just List[father] or List[father[Any,Any]]. 当前类型实际上比List[father]List[father[Any,Any]].更具体List[father[Any,Any]].

EDIT 编辑

Okay now I know what you want. 好吧,我知道你想要什么。

Basically what you want to achieve is that this becomes possible: 基本上,您想要实现的目标是:

val mapped: List[father[Any,Any]] = both.map(x =>
  x match {
    case i:List[String] => func_sonA(i)
    case i:List[Int] => func_sonB(i)
  }
)

The problem here is, that currently with 这里的问题是,目前

class father[T,K] extends HashMap[T,K]

The scala compiler does not know that eg father[String,Long] is supposed to be a subtype of father[Any,Any] (this does not automatically result from String and Long being subtypes of Any ). Scala编译器不知道例如father[String,Long]应该是father[Any,Any]的子类型(这不会自动由于StringLongAny子类型而导致)。 So, to tell Scala that the above should be applicable, you need the class father to be covariant in both type parameters: 因此,要告诉Scala上面的方法适用,您需要在两个类型参数中使father类协变:

class father[+T,+K] 

The problem with that is, that you are extending HashMap[T,K] . 这样做的问题是,您正在扩展HashMap[T,K] But this class is only covariant in the first type Parameter T , but not K . 但是此类仅在第一类型参数T是协变的,而在K不是。

So this code here actually works, but it is not extending HashMap : 因此,此代码实际上有效,但未扩展HashMap

class father[+T,+K]
class sonA[T] extends father[T, Long]
class sonB[T] extends father[T, Double]

def func_sonA[T](x: List[T]) = {
  // code
  new sonA[T]
}

def func_sonB[T](x: List[T]) = {
  // code
  new sonB[T]
}

val strList = List("one", "two", "three", "four")
val intList = List(1,2,3,4)
val both = List(strList, intList)

val mapped: List[father[Any,Any]] = both.map(x =>
  x match {
    case i:List[String] => func_sonA(i)
    case i:List[Int] => func_sonB(i)
  }
)

def bar(x: List[father[Any, Any]]) = {
  println(x)
}
bar(mapped)

Further readings on covariance here . 有关协方差的更多信息,请点击这里

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM