具有不同类型的可变列表的 Scala 重载构造函数
Scala overload constructor with mutable List of different type
我正在尝试使用 Int 和 Long 的可变列表重载构造函数,它提到该方法已经定义。
我需要 updateList
为 mutable.MutableList[Int]
或 mutable.MutableList[Long]
object PercentileDistribution {
def apply(updateList: mutable.MutableList[Int], percentileDistribution: PercentileDistribution): PercentileDistribution = {
updateList.foreach { x =>
percentileDistribution.update(x)
}
percentileDistribution
}
def apply(updateList: mutable.MutableList[Long], percentileDistribution: PercentileDistribution): PercentileDistribution = {
updateList.foreach { x =>
percentileDistribution.update(x)
}
percentileDistribution
}
}
作为 scala 的新手,我遇到了一些问题,感谢您的帮助。
该错误显然与您的代码中发生的向上转换有关。
Int
可以表示为 Long
,因此您基本上编写了相同的方法,其中一个方法参数是另一个应用方法参数的升级版本。
您可以简单地使用具有 MutableList[Long]
类型的应用方法并删除具有 Int
的方法。
按照官方 Scala 文档中的 documentation,您将对类型在 Scala 中的行为有一个很好的了解
错误指的是type erasure。另一个答案错误地指出它与转换有关(尽管类型擦除会导致 casting-related 问题)。
在 Scala REPL 会话中完成的快速示例:
scala> class Foo {
| def bar(list: List[Int]) = "ints"
| def bar(list: List[String]) = "strings"
| }
<console>:12: error: double definition:
def bar(list: List[Int]): String at line 11 and
def bar(list: List[String]): String at line 12
have same type after erasure: (list: List)String
def bar(list: List[String]) = "strings"
^
这里的消息是说两个 bar
方法在编译后的输出中都会有类似 def bar(list: List): String
的类型签名;类型擦除删除了 [Int]
和 [String]
参数,使这两种方法无法区分。如果您在 JVM 上编写 运行 代码,那将是您不得不忍受的烦恼。
我推荐的解决方法是通过名称区分方法,例如而不是 apply
你可以称它为 forInts
和 forLongs
.
另请注意,类型擦除会导致另一个问题:
scala> List(1,2,3).isInstanceOf[List[String]]
<console>:11: warning: fruitless type test: a value of type List[Int] cannot also be a List[String] (the underlying of List[String]) (but still might match its erasure)
List(1,2,3).isInstanceOf[List[String]]
^
res5: Boolean = true
和
scala> List(1, 2, 3) match {
| case l: List[String] => l // you'd think this shouldn't match, but it does
| }
<console>:12: warning: fruitless type test: a value of type List[Int] cannot also be a List[String] (the underlying of List[String]) (but still might match its erasure)
case l: List[String] => l // you'd think this shouldn't match, but it does
^
res2: List[Int] with List[String] = List(1, 2, 3)
scala> res2.head
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
... 33 elided
由于在编译后的字节码中,List[Int]
和List[String]
都只表示为List
,运行时实际上无法区分两者,所以isInstanceOf
检查可能会提供错误的答案,可能会导致 ClassCastExceptions,因为它试图将 Int
视为 String
.
在你的情况下你可能会逃脱它,因为将 Int
转换为 Long
是安全的,但最好完全避免未经检查的转换。
我正在尝试使用 Int 和 Long 的可变列表重载构造函数,它提到该方法已经定义。
我需要 updateList
为 mutable.MutableList[Int]
或 mutable.MutableList[Long]
object PercentileDistribution {
def apply(updateList: mutable.MutableList[Int], percentileDistribution: PercentileDistribution): PercentileDistribution = {
updateList.foreach { x =>
percentileDistribution.update(x)
}
percentileDistribution
}
def apply(updateList: mutable.MutableList[Long], percentileDistribution: PercentileDistribution): PercentileDistribution = {
updateList.foreach { x =>
percentileDistribution.update(x)
}
percentileDistribution
}
}
作为 scala 的新手,我遇到了一些问题,感谢您的帮助。
该错误显然与您的代码中发生的向上转换有关。
Int
可以表示为 Long
,因此您基本上编写了相同的方法,其中一个方法参数是另一个应用方法参数的升级版本。
您可以简单地使用具有 MutableList[Long]
类型的应用方法并删除具有 Int
的方法。
按照官方 Scala 文档中的 documentation,您将对类型在 Scala 中的行为有一个很好的了解
错误指的是type erasure。另一个答案错误地指出它与转换有关(尽管类型擦除会导致 casting-related 问题)。
在 Scala REPL 会话中完成的快速示例:
scala> class Foo {
| def bar(list: List[Int]) = "ints"
| def bar(list: List[String]) = "strings"
| }
<console>:12: error: double definition:
def bar(list: List[Int]): String at line 11 and
def bar(list: List[String]): String at line 12
have same type after erasure: (list: List)String
def bar(list: List[String]) = "strings"
^
这里的消息是说两个 bar
方法在编译后的输出中都会有类似 def bar(list: List): String
的类型签名;类型擦除删除了 [Int]
和 [String]
参数,使这两种方法无法区分。如果您在 JVM 上编写 运行 代码,那将是您不得不忍受的烦恼。
我推荐的解决方法是通过名称区分方法,例如而不是 apply
你可以称它为 forInts
和 forLongs
.
另请注意,类型擦除会导致另一个问题:
scala> List(1,2,3).isInstanceOf[List[String]]
<console>:11: warning: fruitless type test: a value of type List[Int] cannot also be a List[String] (the underlying of List[String]) (but still might match its erasure)
List(1,2,3).isInstanceOf[List[String]]
^
res5: Boolean = true
和
scala> List(1, 2, 3) match {
| case l: List[String] => l // you'd think this shouldn't match, but it does
| }
<console>:12: warning: fruitless type test: a value of type List[Int] cannot also be a List[String] (the underlying of List[String]) (but still might match its erasure)
case l: List[String] => l // you'd think this shouldn't match, but it does
^
res2: List[Int] with List[String] = List(1, 2, 3)
scala> res2.head
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
... 33 elided
由于在编译后的字节码中,List[Int]
和List[String]
都只表示为List
,运行时实际上无法区分两者,所以isInstanceOf
检查可能会提供错误的答案,可能会导致 ClassCastExceptions,因为它试图将 Int
视为 String
.
在你的情况下你可能会逃脱它,因为将 Int
转换为 Long
是安全的,但最好完全避免未经检查的转换。