为什么scalac抱怨String上的method +?

Fra*_*eil 2 types scala

给出以下Scala代码:

def stream(callback: (String, Array[Byte]) => Unit) {
    callback("application/json;charset=utf-8", Array(1))
    callback("application/xml;charset=utf-8", Array(1))
}

@Test
def whenStreaming_thenShouldSeeSameMessages() {
    var actualMessages = List.empty[(String, Array[Byte])]
    sut.stream {
        (contentType, payload) =>
            actualMessages += (contentType, payload)
    }

    expect(List("application/json;charset=utf-8", "application/xml;charset=utf-8")) {
        actualMessages
    }
}
Run Code Online (Sandbox Code Playgroud)

为什么我收到以下错误消息:

error: too many arguments for method +: (other: String)java.lang.String
actualMessages += (contentType, payload)
Run Code Online (Sandbox Code Playgroud)

具体而言,有效负载在IDEA中突出显示,在命令行中,+ =突出显示.我真的不明白这个错误信息.

Kip*_*ros 6

实际上,创建带有附加元素的新列表的方法:+.要var使用附加版本更新列表,您需要这样做,

actualMessages :+= (contentType, payload)
Run Code Online (Sandbox Code Playgroud)

或者你可以在前面加上,

actualMessages +:= (contentType, payload)
// or, equivalently,
// actualMessages ::= (contentType, payload)
Run Code Online (Sandbox Code Playgroud)

(对于大型列表,预先添加实际上是可取的,因为它是O(1)而不是O(n)用于追加.一种策略是使用前置来反向构建列表,然后在结束调用时使用List.reverse.)

对于+您尝试使用的运算符,Scala认为您想要进行字符串连接,

scala> List("hello") + " world"
res0: java.lang.String = List(hello) world
Run Code Online (Sandbox Code Playgroud)

这是Java的遗憾结转.使用scala.Predef中定义的隐式转换在Scala中实现通用字符串连接,

implicit def any2stringadd (x: Any): StringAdd 
Run Code Online (Sandbox Code Playgroud)

发生的事情是List没有实现一个+方法,因此编译器会寻找转换为提供+和查找的东西any2stringadd.这是例如true + " false"有效的方式.