我Named Arguments
在Scala中深入研究这个例子:
scala> class Parent { | def foo(bar: Int = 1, baz: Int = 2): Int = bar + baz | } defined class Parent scala> class Child extends Parent { | override def foo(baz: Int = 3, bar: Int = 4): Int = super.foo(baz, bar) | } defined class Child scala> val p = new Parent p: Parent = Parent@6100756c scala> p.foo() res1: Int = 3 scala> val x = new Child x: Child = Child@70605759
x.foo()
由于Child#foo
默认参数为3和4,因此调用求值为7 .
scala> x.foo() res3: Int = 7
Child
在运行时实例化一个新的,但是Parent
在编译时.这可能是也可能不正确
scala> val y: Parent = new Child y: Parent = Child@540b6fd1
x.foo()
由于Child#foo
默认参数为3和4,因此调用求值为7 .
scala> y.foo() res5: Int = 7
x.foo()
由于Child#foo
默认baz
参数为3,因此调用计算结果为4 .
scala> x.foo(bar = 1) res6: Int = 4
但是,我不明白为什么会y.foo(bar = 1)
返回5.我会期望Child#foo
被评估,因为它y
是一种Child
类型.传入bar
1的a foo
表示baz
默认值为3.因此它应该产生4.但我的理解当然是不正确的.
scala> y.foo(bar = 1) res7: Int = 5
senia.. 7
有两个原因:
scala
编译器为默认参数创建辅助方法:
val p = new Parent() val c = new Child() p.`foo$default$1` // Int = 1 p.`foo$default$2` // Int = 2 c.`foo$default$1` // Int = 3 c.`foo$default$2` // Int = 4
这就是为什么你不仅可以使用常量,还可以使用默认参数的字段和方法:
def test(i: Int = util.Random.nextInt) = i test() // Int = -1102682999 test() // Int = -1994652923
编译后没有命名参数 - 所有参数都是位置参数.
所以既然bar
是Child#foo
这段代码的第二个参数:
c.foo(bar = 1) // Int = 4
由编译器翻译为:
c.foo(c.`foo$default$1`, /*bar = */1) // Int = 4
但是因为bar
是Parent#foo
这段代码的第一个参数:
val tmp: Parent = c tmp.foo(bar = 1) // Int = 5
被翻译成这个:
tmp.foo(/*bar = */1, tmp.`foo$default$2`) // Int = 5
因为我们已经知道c.foo$default$2
返回4
,所以c.foo(1, 4)
返回5.
有两个原因:
scala
编译器为默认参数创建辅助方法:
val p = new Parent() val c = new Child() p.`foo$default$1` // Int = 1 p.`foo$default$2` // Int = 2 c.`foo$default$1` // Int = 3 c.`foo$default$2` // Int = 4
这就是为什么你不仅可以使用常量,还可以使用默认参数的字段和方法:
def test(i: Int = util.Random.nextInt) = i test() // Int = -1102682999 test() // Int = -1994652923
编译后没有命名参数 - 所有参数都是位置参数.
所以既然bar
是Child#foo
这段代码的第二个参数:
c.foo(bar = 1) // Int = 4
由编译器翻译为:
c.foo(c.`foo$default$1`, /*bar = */1) // Int = 4
但是因为bar
是Parent#foo
这段代码的第一个参数:
val tmp: Parent = c tmp.foo(bar = 1) // Int = 5
被翻译成这个:
tmp.foo(/*bar = */1, tmp.`foo$default$2`) // Int = 5
因为我们已经知道c.foo$default$2
返回4
,所以c.foo(1, 4)
返回5.