Scala和Java-隐式参数和继承 [英] Scala and Java - Implicit Parameters and Inheritance

查看:156
本文介绍了Scala和Java-隐式参数和继承的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下代码给出错误:

package test

trait Base {
  def method:String
}

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

object Object extends Trait {

}

错误为无法创建对象,因为未定义类型=>字符串的Base类中的方法""

上述错误已通过以下代码修复

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 {

}

现在,当我如下定义Java接口时,代替Scala类:

// 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:字符串)字符串和类型的特征特质类型中的方法方法() "

在这两种情况下,使编译器的行为有所不同的区别是什么?我该如何解决这个问题?

解决方案

下面是一个示例,我认为它清楚地说明了正在发生的事情:

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:有括号,用括号括起来,一切都很好.
  • B:没有 括号,但是超类型没有带有括号,因此还是不错的.这与您的情况相对应.
  • C:没有括号,用括号来调用,没有好处.

基本上,Java方法通常被认为带有括号",因此,Trait的超类型具有括号,因此在method()("string")中使用括号不足以阐明您的意思.


编辑:坦白地说,我认为您最好重命名该方法.即使在没有歧义的情况下,其行为也可能令人惊讶:

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"

此外,名称相同的事实并不能为您带来任何好处:仅非隐式方法会覆盖Base.method,这是从美学角度考虑使名称相同./p>

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"

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:

// 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 ()"

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.
  • B: Has no parentheses, but supertype does have parentheses, so still good. This corresponds to your case.
  • C: Has no parentheses, called with parentheses, no good.

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.


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.

这篇关于Scala和Java-隐式参数和继承的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆