1

我在 Scala 2.10.2 上并试图定义一个像

trait Foo {
  def bar(a:String): String
  def bar(a:String): Int
}

得到编译器错误method a is defined twice。什么是正确的语法?

4

4 回答 4

8

用一点推拉

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 = f.bar("x")
  val i: Int = f.bar("x")
  println(s)
  println(i)
}

您可以调整它,使用 a DummyImplicit(绕过“方法定义两次”)和显式类型(选择其中一种方法)。

于 2013-07-26T20:13:37.140 回答
6

在 JVM 上,方法的返回类型不是方法签名的一部分。您必须提供不同的方法名称或参数。来自 Oracle文档

定义:方法声明的两个组成部分包括方法签名——方法的名称和参数类型。

您正在尝试做的事情称为方法重载,Oracle 说如下:

编译器在区分方法时不考虑返回类型,因此即使它们具有不同的返回类型,也不能声明具有相同签名的两个方法。

因为Scala也编译成JVM字节码,规则是一样的

于 2013-07-26T19:02:54.950 回答
3

我真的不知道为什么它会有用,但你可以这样做:

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

scala> Foo.bar[Int]("asdf")
res8: Int = 1

scala> Foo.bar[Boolean]("asdf")
res9: Boolean = true
于 2013-07-27T06:04:12.920 回答
2

来自维基:http ://en.wikipedia.org/wiki/Function_overloading

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.

仅具有不同的返回类型不算作函数重载,也是不允许的。

于 2013-07-26T19:10:31.760 回答