Scala and Java - Implicit Parameters and Inheritance

The following code gives an error:

package test trait Base { def method:String } trait Trait extends Base { def method()(implicit i:String):String = { "2" } } object Object extends Trait { } 

Error creating object "because the method of the method in the Base type => String class is not defined"

The indicated error is fixed by the following code

 package test trait Base { def method:String } trait Trait extends Base { def method:String = method()("String") // Over loading def method()(implicit i:String):String = { "2" } } object Object extends Trait { } 

Now instead of the Scala class, when I define the Java interface as follows:

 // Java Code package test; public interface JBase { String method(); } // Scala Code package test trait Trait extends JBase { def method:String = method()("10") def method()(implicit i:String):String = { "2" } } object Object extends Trait { } 

I get the error "an ambiguous reference to an overloaded definition, as a method method in the Trait attribute of type () (implicit i: String) A String method and a method in the Trait attribute of type () Argument types with strings ()"

What is the difference in both of these scenarios that cause the compiler to behave differently? How to solve this problem?

+4
source share
1 answer

Here is an example that I think clearly shows what is happening:

 object Test extends App { class A { def f(): String = "x" } class B extends A { override def f: String = "y" } class C { def f: String = "z" } println { (new A).f() } // OK println { (new B).f() } // OK println { (new C).f() } // FAILS } 
  • A : has parentheses, is called with parentheses, all is well.
  • B : doesn't have parentheses, but the supertype has parentheses, so it's still good. It matches your case.
  • C : doesn't have parentheses called with parentheses, and nothing good.

Basically, Java methods are always counted β€œwith parentheses,” so the Trait supertype has parentheses, so using parentheses in method()("string") not enough to specify which method you have in mind.


edit . Honestly, I think you better rename this method. Even in the absence of ambiguity, the behavior can be quite unexpected:

 trait Trait { def method: String = method()("x") def method()(implicit i: String): String = i } val t = new Trait { } implicit val s = "y" println { t.method } > "x" println { t.method() } > "y" 

In addition, the fact that the name is the same does not buy you anything in terms of polymorphism: only an implicit method redefines Base.method - it is just an aesthetic decision to make the names the same.

+7
source

All Articles