虽然可能存在这样的方法过载可能变得模糊的有效情况,但为什么编译器不允许在编译时和运行时都不模糊的代码?
例:
// This fails:
def foo(a: String)(b: Int = 42) = a + b
def foo(a: Int) (b: Int = 42) = a + b
// This fails, too. Even if there is no position in the argument list,
// where the types are the same.
def foo(a: Int) (b: Int = 42) = a + b
def foo(a: String)(b: String = "Foo") = a + b
// This is OK:
def foo(a: String)(b: Int) = a + b …Run Code Online (Sandbox Code Playgroud) 我知道类型擦除使它们在运行时看起来相同,类型,所以:
class Bar {
def foo[A](xs: A*) { xs.foreach(println) }
def foo[A, B](xs: (A, B)*) { xs.foreach(x => println(x._1 + " - " + x._2)) }
}
Run Code Online (Sandbox Code Playgroud)
给出以下编译器错误:
<console>:7: error: double definition:
method foo:[A,B](xs: (A, B)*)Unit and
method foo:[A](xs: A*)Unit at line 6
have same type after erasure: (xs: Seq)Unit
def foo[A,B](xs: (A, B)*) { xs.foreach(x => println(x._1 + " - " + x._2)
) }
^
Run Code Online (Sandbox Code Playgroud)
但是有一种简单的方法可以写:
bar.foo(1, 2, 3)
bar.foo(1 -> 2, 3 -> 4)
Run Code Online (Sandbox Code Playgroud)
并让这些调用foo的不同重载版本,而不必明确命名它们:
bar.fooInts(1, 2, …Run Code Online (Sandbox Code Playgroud) 说你有以下内容:
foo(x: String)(y: Int): Int
foo(x: String)(y: Double): Int
Run Code Online (Sandbox Code Playgroud)
Scala不允许这样的表达.据我所知,其原因是foo("asdf")没有明确定义的类型(它是Int => Int或Double => Int).
是否有理由不允许这种"多型"功能?
我在Scala中有这个类:
object Util {
class Tapper[A](tapMe: A) {
def tap(f: A => Unit): A = {
f(tapMe)
tapMe
}
def tap(fs: (A => Unit)*): A = {
fs.foreach(_(tapMe))
tapMe
}
}
implicit def tapper[A](toTap: A): Tapper[A] = new Tapper(toTap)
}
Run Code Online (Sandbox Code Playgroud)
现在,
"aaa".tap(_.trim)
Run Code Online (Sandbox Code Playgroud)
不编译,给出错误
错误:扩展函数缺少参数类型((x $ 1)=> x $ 1.trim)
为什么不推断类型String?从错误看来,隐式转换似乎触发了(否则错误将沿着" tap不是类的成员String"的行).似乎转换必须是Tapper[String],这意味着参数的类型是String => Unit(或(String => Unit)*).
有趣的是,如果我注释掉任何一个tap定义,那么它就会编译.
我有以下内容:
def calc(dir: File): Option[Group] = {
calcModel(dir) match {
case Some(model: Model) => calcUI(model, centerpane.getWidth, centerpane.getHeight, 5, MAX_LEVEL)
case None => None
}
}
def calcUI(model: Model, availableWidth: Double, availableHeight: Double, maxLevel: Int): Option[Group] = {
}
def calcUI(model: Model, posX: Double, posY: Double, availableWidth: Double, availableHeight: Double, horizontally: Boolean, startLevel: Int, maxLevel: Int): Option[Group] = {
}
protected def calcUI(node: Node, posX: Double, posY: Double, availableWidth: Double, availableHeight: Double, horizontally: Boolean, level: Int, maxLevel: Int): Group = { …Run Code Online (Sandbox Code Playgroud) import swing._
object PeerTest extends SimpleSwingApplication {
def top = new MainFrame {
val p = peer.getMousePosition
}
}
Run Code Online (Sandbox Code Playgroud)
给
error: ambiguous reference to overloaded definition,
both method getMousePosition in class Container of type (x$1: Boolean)java.awt.Point
and method getMousePosition in class Component of type ()java.awt.Point
match expected type ?
val p = peer.getMousePosition
Run Code Online (Sandbox Code Playgroud)
但添加类型
val p: Point = peer.getMousePosition
Run Code Online (Sandbox Code Playgroud)
没事.为什么?
编辑:导致问题:
class A {
def value() = 123
}
class B extends A {
def value(b: Boolean) = 42 …Run Code Online (Sandbox Code Playgroud) 我试图根据参数是否扩展给定的类来重载方法,并且遇到了一些麻烦.使用Miles Sabin的方法,我产生了以下代码:
object ExtendedGenericTypes {
trait <:!<[A, B] // Encoding for "A is not a subtype of B"
// Use ambiguity to rule out the cases we're trying to exclude
implicit def nsubAmbig1[A, B >: A]: A <:!< B = null
implicit def nsubAmbig2[A, B >: A]: A <:!< B = null
// The implicit substitutions
implicit def nsub[A, B]: A <:!< B = null
}
Run Code Online (Sandbox Code Playgroud)
而我的用例:
import ExtendedGenericTypes._
class Foo
def foobar[T](x: T)(implicit ev: T <:< Foo) …Run Code Online (Sandbox Code Playgroud) 我在以下两种方法上收到双重定义错误:
def apply[T](state: T, onRender: T => Graphic,
onMouseEvent: (MouseEvent, T) => T): GraphicPanel =
apply(state, onRender, onMouseEvent = Some(onMouseEvent))
Run Code Online (Sandbox Code Playgroud)
和
def apply[T](state: T, onRender: T => Graphic,
onKeyEvent: (KeyEvent, T) => T): GraphicPanel =
apply(state, onRender, onKeyEvent = Some(onKeyEvent))
Run Code Online (Sandbox Code Playgroud)
对于apply带有签名的更通用方法,它们都是方法重载:
def apply[T](state: T, onRender: T => Graphic,
onTickEvent: Option[T => T] = None, fps: Int = 30,
onMouseEvent: Option[(MouseEvent, T) => T] = None,
onMouseMotionEvent: Option[(MouseEvent, T) => T] = None,
onMouseInputEvent: Option[(MouseEvent, T) => T] = …Run Code Online (Sandbox Code Playgroud) scala 2.9.2这个编译很好
object AppBuilder extends App {
def app( blockw: Int => String ) : List[String] = List( blockw(6) )
def app( block: => String ) : List[String] = app( _ => block )
}
Run Code Online (Sandbox Code Playgroud)
但是在REPL中,与上面相同的方法/函数(不确定这里的区别),如果没有包含在类中,我会得到以下错误
scala> def app( blockw: Int => String ) : List[String] = List( blockw(6) )
app: (blockw: Int => String)List[String]
scala> def app( block: => String ) : List[String] = app( _ => block )
<console>:8: error: missing parameter type
def app( block: => String …Run Code Online (Sandbox Code Playgroud) def createFloatBuffer(data: Option[Quaternion]*): Option[FloatBuffer] = data match {
...
}
def createFloatBuffer(data: Option[Vector3f]*): Option[FloatBuffer] = data match {
...
}
Run Code Online (Sandbox Code Playgroud)
由于两种方法具有相同的方法签名,因此不会编译此代码.没有类型不知道调用哪种方法.
我可以重命名方法,但是我想在我的代码中重载样式.
我有一个带有选项参数的case类,让我们说:
case class Student(id: Option[Int], name: String)
Run Code Online (Sandbox Code Playgroud)
要获得Student实例,不仅我可以使用Student(Some(1), "anderson"),我还希望这个表单是一种有效的方式Student(2,"Sarah")
我想我必须创建一个Int => Option[Int]并把它放在某个地方.那么最好的方法是什么?
更新
正如评论中提到的,override apply方法将阻止调用它Student.apply _
scala ×11
overloading ×6
types ×2
currying ×1
default ×1
methods ×1
scala-swing ×1
type-erasure ×1