在返回类型上重载?

Gre*_*ena 12 scala

scala> val shares = Map("Apple" -> 23, "MicroSoft" -> 50, "IBM" -> 17)
shares: scala.collection.immutable.Map[java.lang.String,Int] 
      = Map(Apple -> 23, MicroSoft -> 50, IBM -> 17)

scala> val shareholders = shares map {_._1}                           
shareholders: scala.collection.immutable.Iterable[java.lang.String] 
            = List(Apple, MicroSoft, IBM)

scala> val newShares = shares map {case(k, v) => (k, 1.5 * v)}     
newShares: scala.collection.immutable.Map[java.lang.String,Double] 
         = Map(Apple -> 34.5, MicroSoft -> 75.0, IBM -> 25.5)
Run Code Online (Sandbox Code Playgroud)

从这个例子看,这个map方法似乎在返回类型上重载.在返回类型上重载是不可能的?有人请解释这里发生了什么?

ret*_*nym 13

map在返回类型上没有重载.相反,有一种方法具有抽象返回类型.

def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That
Run Code Online (Sandbox Code Playgroud)

在字节码中,这被删除为Object:

public abstract java.lang.Object map(scala.Function1, scala.collection.generic.CanBuildFrom);
Run Code Online (Sandbox Code Playgroud)

该模式在" 与类型搏斗位腐蚀"一文中有最好的描述

  • 这是自从我开始编程以来我见过的最可怕的事情. (4认同)
  • 编写这种`map`方法很难,但通常很容易使用. (3认同)

Ale*_*nov 6

这不是发生了什么事情在这种情况下,但实际上是,超载的返回类型由JVM支持.这在Scala中暴露给具有不同泛型参数类型的方法,这些方法类型擦除到相同类型.链接中给出的示例是

object Overload{
  def foo(xs : String*) = "foo"; // after erasure is foo:(Seq)String
  def foo(xs : Int*) = 3;        // after erasure is foo:(Seq)Int
}
Run Code Online (Sandbox Code Playgroud)