[英]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 {
}
The error is "object creation impossible, since method method in class Base of type => String is not defined" 错误是“对象创建不可能,因为类型为Base的方法方法=>字符串未定义”
The above error is fixed by 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 Scala class, when I define a Java interface as follows: 现在我代替Scala类,当我定义一个Java接口时,如下所示:
// 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 an error "ambiguous reference to overloaded definition, both method method in trait Trait of type ()(implicit i: String)String and method method in trait Trait of type ()String match argument types ()" 我得到一个错误“对重载定义的模糊引用,特征中的方法方法Traint of type()(隐式i:String)特征中的字符串和方法方法类型的特征()字符串匹配参数类型()”
What is the difference in both these scenarios that makes the compiler behave differently? 这两种场景的不同之处在于编译器的行为方式有何不同? How do I solve this issue?
我该如何解决这个问题?
Here's an example that I think shows clearly what is going on: 这是一个我认为清楚显示正在发生的事情的例子:
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, called with parentheses, everything good. A
:有括号,用括号括起来,一切都很好。 B
: Has no parentheses, but supertype does have parentheses, so still good. B
: 没有括号,但是超类型确实有括号,所以仍然很好。 This corresponds to your case. C
: Has no parentheses, called with parentheses, no good. C
:没有括号,括号括起来,没有好处。 Basically, Java methods are always considered "with parentheses", so, Trait
's supertype has the parentheses, so using parentheses in method()("string")
is insufficient to clarify which method you mean. 基本上,Java方法总是被认为是“括号”,因此,
Trait
的超类型具有括号,因此在method()("string")
使用括号不足以阐明您的方法。
edit : Honestly I think you are better off renaming the method. 编辑 :老实说,我认为你最好重命名方法。 Even in the case where there is no ambiguity, the behavior could be quite surprising:
即使在没有歧义的情况下,行为也可能非常令人惊讶:
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"
Furthermore, the fact that the name is the same isn't buying you anything in terms of polymorphism: only the non-implicit method overrides Base.method
-- it's just an aesthetic decision to make the names be the same. 此外,名称相同的事实并不是就多态性而购买任何东西:只有非隐式方法会覆盖
Base.method
- 这只是一个美学决定,使名称相同。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.