Accepted answer

With a little push and pull

trait Foo {
  def bar(a:String): String
  def bar(a:String)(implicit di: DummyImplicit): Int

class F extends Foo {
  def bar(a: String): String = "Hello"
  def bar(a: String)(implicit di: DummyImplicit): Int = 1

object Demo extends App {
  val f = new F()
  val s: String ="x")
  val i: Int ="x")

you can tweak it, using a DummyImplicit (to get around "Method is defined twice") and explicit typing (to pick one of the methods).


From wiki:

Rules in function overloading

* The overloaded function must differ either by the arity or data types.
* The same function name is used for various instances of function call.

Only having different return types does not count as function overloading, and is not allowed.


I can't really tell why it would be useful, but you could do this:

scala> object Foo {
     | trait BarImpl[T] { def apply(str: String): T }
     | implicit object barInt extends BarImpl[Int] { def apply(str: String) = 1 }
     | implicit object barBoolean extends BarImpl[Boolean] { def apply(str: String) = true }
     | def bar[T](str: String)(implicit impl: BarImpl[T]) = impl(str)
     | }
defined module Foo

res8: Int = 1

res9: Boolean = true


On the JVM the return type of a method is not a part of a method signature. You have to give different method names or parameters. From Oracle Docs:

Definition: Two of the components of a method declaration comprise the method signature—the method's name and the parameter types.

What you are tryng to do is called Method overloading and Oracle says the following:

The compiler does not consider return type when differentiating methods, so you cannot declare two methods with the same signature even if they have a different return type.

Cause Scala also compiles to JVM byte code, rules are the same

Related Query

More Query from same tag