1

I have a follow-on question to the problem that the presence of overloaded method definitions with and without parameters leads to a compilation error, which is already discussed here: Why is this reference ambiguous?

To recap:

 trait A { 
    def foo( s: String ) : String
    def foo : String = foo( "foo" )
 }
 object B extends A {
    def foo( s: String ) : String = s
 } 
 B.foo     // won't compile

results in the error message:

 error: ambiguous reference to overloaded function
 both method foo in object B of type(s: String)String
 and method foo in trait A of type => String
 match expected type Unit
 B.foo

A solution that works is to provide the compiler with the expected type, like so:

 val s: String = B.foo

Unfortunately, one may not always want to introduce an extra variable (e.g. within an assertion). One of the solutions recommended at least twice in the answers to the earlier article referenced above was to invoke the method with empty parentheses, like so:

 B.foo()

Unfortunately, this leads to a similar compiler error (Scala 2.9.0.1):

 (s: String)String <and>
 => String
 cannot be applied to ()
 B.foo()

Is this a bug, or was the recommended solution in error? And ultimately: what options are there to do this concisely, as in:

 assert( B.foo == "whatever" )

instead of

 val expected : String = B.foo
 assert( expected == "whatever" )

Thanks.

Community
  • 1
  • 1
Gregor Scheidt
  • 3,952
  • 4
  • 24
  • 28
  • `B` doesn't compile, because you forgot to provide the implementation for the `def foo: String` in trait `A`. – agilesteel Oct 11 '11 at 05:24
  • @agilesteel right, the implementation of paramless foo on A got lost in the transfer. Fixed that now. Error remains the same. – Gregor Scheidt Oct 11 '11 at 09:02

2 Answers2

6
assert( (B.foo: String) == "whatever" )
agilesteel
  • 16,775
  • 6
  • 44
  • 55
2

You can add empty parenthesis to second foo definition:

trait A { 
  def foo( s: String ) : String
  def foo() : String
}

Then you can remove the disambiguation as explained elsewhere:

assert( B.foo() == "whatever" )
paradigmatic
  • 40,153
  • 18
  • 88
  • 147
  • This is also a good answer, thanks. One potential downside is that if the paramless foo() collides with overloaded alternatives only in some derived classes (say, if it came from even higher up than A) it will still force all invocations, even below siblings of A, to now use empty parentheses to call it (at least if you don't want you IDE to flag the invocations when you leave the parentheses out). – Gregor Scheidt Oct 11 '11 at 09:08