Compiler do not recognize function overloading because types are erased. How to overcome this?
parametric-polymorphism, scala
Solution
The compiler does see a difference between them, it is just not allowed to use this difference in overloading (since erasures of `Some[(Int, String) => Unit]` and `Some[Int => Unit]` are the same and JVM doesn't allow overloading when erasures of arguments are the same). The solution is to add fake implicit arguments:
class Foo() {
def fooSome(block: Some[(Int, String) => Unit]) = {
}
def fooSome(block: Some[Int => Unit])(implicit d: DummyImplicit) = {
}
}
Also note that erasures of `fooNoSome` are `fooNoSome(Function2)` and `fooNoSome(Function1)`, so if you wanted to add another overload which takes any function of one or two arguments, you'd need the `DummyImplicit` trick again:
def fooNoSome(block: Double => Unit)(implicit d: DummyImplicit) = ...
Problem
I have a problem that the two methods named fooSome in the code below don't compile as the compiler reports a problem with duplicate method names: ``` 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) = { } } ``` On the contrary the compiler reports no such method name collision with the two methods named fooNoSome. So the problem is that the compiler doesn't see a difference between "Some[(Int, String) => Unit]" and "Some[(Int) => Unit]" whereas "(Int, String) => Unit" is seen as a different signature than "(Int) => Unit" as for the fooNoSome methods. I could work around this by creating a class Some2Args that is used for the "Some[(Int, String) => Unit]" case and a class Some1Arg for the "Some[(Int) => Unit]" case. My question is whether there is a more elegant and less effortful solution.