Scala命名为参数
我正在查看
Scala in Depth中的这个命名参数示例:
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 由于Child#foo的默认参数为3和4,因此调用x.foo()的计算结果为7. scala> x.foo() res3: Int = 7 在运行时实例化一个新的Child,但在编译时实例化Parent.这可能是也可能不正确 scala> val y: Parent = new Child y: Parent = Child@540b6fd1 由于Child#foo的默认参数为3和4,因此调用x.foo()的计算结果为7. scala> y.foo() res5: Int = 7 调用x.foo()的计算结果为4,因为Child#foo的默认baz参数为3. scala> x.foo(bar = 1) res6: Int = 4 但是,我不明白为什么y.foo(bar = 1)返回5.我希望Child#foo被评估,因为y是Child类型.传入一个1到foo的小节意味着baz的默认值是3.所以它应该产生4.但是我的理解当然是不正确的. scala> y.foo(bar = 1) res7: Int = 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. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |