I wrote this in scala and it won't compile:
class TestDoubleDef{
def foo(p:List[String]) = {}
def foo(p:List[Int]) = {}
}
the compiler notify:
[error] double definition:
[error] method foo:(List[String])Unit and
[error] method foo:(List[Int])Unit at line 120
[error] have same type after erasure: (List)Unit
I know JVM has no native support for generics so I understand this error.
I could write wrappers for List[String]
and List[Int]
but I'm lazy :)
I'm doubtful but, is there another way expressing List[String]
is not the same type than List[Int]
?
Thanks.
If I combine Daniels response and Sandor Murakozis response here I get:
I get a typesafe(ish) variant
The logic may also be included in the type class as such (thanks to jsuereth): @annotation.implicitNotFound(msg = "Foo does not support ${T} only Int and String accepted") sealed trait Foo[T] { def apply(list : List[T]) : Unit }
Which gives:
Note that we have to write
implicitly[Foo[A]].apply(x)
since the compiler thinks thatimplicitly[Foo[A]](x)
means that we callimplicitly
with parameters.I like Michael Krämer's idea to use implicits, but I think it can be applied more directly:
I think this is quite readable and straightforward.
[Update]
There is another easy way which seems to work:
For every version you need an additional type parameter, so this doesn't scale, but I think for three or four versions it's fine.
[Update 2]
For exactly two methods I found another nice trick:
Instead of inventing dummy implicit values, you can use the
DummyImplicit
defined inPredef
which seems to be made exactly for that:Instead of using manifests you could also use dispatchers objects implicitly imported in a similar manner. I blogged about this before manifests came up: http://michid.wordpress.com/code/implicit-double-dispatch-revisited/
This has the advantage of type safety: the overloaded method will only be callable for types which have dispatchers imported into the current scope.
Due to the wonders of type erasure, the type parameters of your methods' List get erased during compilation, thus reducing both methods to the same signature, which is a compiler error.
I tried improving on Aaron Novstrup’s and Leo’s answers to make one set of standard evidence objects importable and more terse.
But that will cause the compiler to complain that there are ambiguous choices for the implicit value when
foo
calls another method which requires an implicit parameter of the same type.Thus I offer only the following which is more terse in some cases. And this improvement works with value classes (those that
extend AnyVal
).If the containing type name is rather long, declare an inner
trait
to make it more terse.However, value classes do not allow inner traits, classes, nor objects. Thus also note Aaron Novstrup’s and Leo’s answers do not work with a value classes.