[英]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
基本上意味着该类型是String
或Int
。 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
的第一种类型为String
或Int
,第二种类型为Long
或Double
。
Regarding your other question: 关于其他问题:
How can I specify the type of mapped to be just
List[father]
orList[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]
的子类型(这不会自动由于String
和Long
是Any
子类型而导致)。 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)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.