我在Scala中看到了一个奇怪的片段,我不太明白。对我来说,Scala中的赋值返回Unit
,与Java不同,它返回已影响值的变量类型。但是,让我们考虑这个类:
case class C(i: Int) {
def f = C(i = i + 10)
}
这个编译完全没问题,这很奇怪!工厂方法C.apply
需要Int
,而我传递的类型为Unit
的似乎是赋值。顺便说一句,如果我删除赋值只是让表达式,它似乎有完全相同的行为。
我们现在试试这个:
case class C(i: Int) {
def f = {
i = i + 10
C(i = i + 10)
}
}
好了,现在这是我所知道的世界:i
是一个val,然后你不能改变它,所以i = i + 10
不能编译。但是,C(i = i + 10)
仍然可以编译而不会抱怨。这怪异是什么?这有什么理由存在吗?
答案 0 :(得分:8)
这是因为,在C(i = i + 10)
的情况下,左侧i
不是字段C#i
而是named parameter。根本没有任何任务。
C(i = i + 10)
^ ^
+---|-------- Parameter name
|
+- - - - - - - - - - - - - - Reference to the field `i`
in the instance of the class `C`
命名参数有意义的地方:
避免"这个{boolean, integer}
是什么意思"时刻:
someMethod(anObject, flagName=true)
// As opposed to someMethod(anObject, true) ... what's `true` for?
anotherMethod(arg1, arg2, totalMagic=33)
使用参数的默认值(调用正确的构造函数)时:
def withDefaults(i: Int, flag: Boolean = true, wrapper: Option[String] = None) = {
wrapper.fold(s"$i with $flag")(_.format(i, flag))
}
withDefaults(3, Some("stuff %s around %s"))
// won't compile
// error: type mismatch;
// found : Some[String]
// required: Boolean
withDefaults(3, wrapper = Some("stuff %s around %s"))
// works (returns "stuff 3 around true")