Scala 编译器无法识别函数重载,因为类型已被擦除。如何克服这个问题?
我有一个问题,下面代码中名为fooSome的两个方法无法编译,因为编译器报告了一个方法名重复的问题:Scala 编译器无法识别函数重载,因为类型已被擦除。如何克服这个问题?,scala,parametric-polymorphism,Scala,Parametric Polymorphism,我有一个问题,下面代码中名为fooSome的两个方法无法编译,因为编译器报告了一个方法名重复的问题: class Foo() { // variable block has 2 closure variables def fooSome(block: Some[(Int, String) => Unit]) = { } // variable block has 1 closure variables def fooSome(block: Some[Int =&g
class Foo() {
// variable block has 2 closure variables
def fooSome(block: Some[(Int, String) => Unit]) = {
}
// variable block has 1 closure variables
def fooSome(block: Some[Int => Unit]) = {
}
// variable block has 2 closure variables
def fooNoSome(block: (Int, String) => Unit) = {
}
// variable block has 1 closure variables
def fooNoSome(block: Int => Unit) = {
}
}
相反,编译器报告没有这种方法名与名为fooNoSome的两个方法冲突。所以问题是编译器没有看到“Some[(Int,String)=>Unit]”和“Some[(Int)=>Unit]”之间的区别,而对于foonsome方法,“(Int,String)=>Unit”被视为与“(Int)=>Unit”不同的签名
我可以通过创建一个用于“Some[(Int,String)=>Unit]”案例的类Some2Args和一个用于“Some[(Int)=>Unit]”案例的类Some1Arg来解决这个问题
我的问题是是否有一个更优雅、更省力的解决方案。编译器确实看到了它们之间的区别,只是不允许在重载中使用这种区别(因为删除
Some[(Int,String)=>Unit]
和Some[Int=>Unit]
是相同的,当参数的擦除相同时,JVM不允许重载)。解决方案是添加假隐式参数:
class Foo() {
def fooSome(block: Some[(Int, String) => Unit]) = {
}
def fooSome(block: Some[Int => Unit])(implicit d: DummyImplicit) = {
}
}
还要注意的是,foonsome
的擦除是foonsome(Function2)
和foonsome(Function1)
,因此如果您想添加另一个重载,该重载包含一个或两个参数的函数,您需要再次使用DummyImplicit
技巧:
def fooNoSome(block: Double => Unit)(implicit d: DummyImplicit) = ...
一个更系统的方法,没有虚拟的隐含,应该是这样的:
class Foo() {
def fooSome[X](block: Some[X])(implicit cfs: CanFooSome[X]) = {
cfs.handleThat(block)
}
}
trait CanFooSome[X] {
def handleThat(block: Some[X]): Unit // or other return type
}
// in carefully chosen scope for implicits
implicit object CanFooSomeIntToUnit extends CanFooSome[Int => Unit] {
def handleThat(block: Some[Int => Unit]) = ...
}
// same for all other type combinations, like (Int, String) => Unit etc.
这是因为Scala编译器在编译时决定插入什么
对于CanFooSome实现,JVM在运行时看不到这方面的任何内容。此模式可能具有某些优势(例如可扩展性:可以从外部提供新的CanFooSome,而不会更改Foo的代码),并且不会随着fooSome类型数量的增加而变得更加混乱。可能重复@om nom nom重载和擦除的问题与匹配和擦除不同,这个问题和答案都不是关于超载的。如果以前没有人问过这样的问题,我会很惊讶,但我在快速搜索中找不到重复的问题。谢谢你的回答,亚历克西。认为这解决了我的问题。