一个有趣的定义

shivawu 2010-03-27
今天想到这样一个类的定义方式

class A(f: A => Int) {
  val x = f(this)
}

然后如果这样
new A(_.x + 10).x
会输出10

这只是一个简单的例子,不知道如果把x换成一种对象的类型会是什么结果,原理又是什么呢?
night_stalker 2010-03-28
scala 是"伪脚本",类型是在编译期决定的。在运行构造器的时候,A 已经知道 x 是 Int 类型了,而 Int 的默认值是 0,故在调用 f(this) 的时候, this.x == 0。构造器再将 0 + 10 赋给 x,所以得到了以上结果。

Object 的默认值是 null,例子如下:
class A(f: A => Object) {
  val x = f(this)
}
(new A(if(_.x == null) "null" else "not null")).x


ps: 机器还没装 scala,尚未验证 …… 这个做法很糟糕,如果 x 是一个方法的话,就会无限循环或者爆栈了 ……
cloverprince 2010-04-10
我理解:

类型在编译期推定:
由于f : A => Int,确定f的函数值是Int
由于val x = f(this),确定x的类型也是Int

x是val,那么x的值在对象构造的时候确定:
对象构造的时候,x因为是Int型,所以x的初始值是0。
然后,根据val x = f(this),初始化这个x。得:
x = f(this) = this.x + 10 = 0 + 10 = 10

println的时候,那个对象的x域的值就是10了。


实验证明,和ML,Haskell等函数式语言不同,Scala的各个val的初始化是从前到后一个一个地完成的,定义的顺序影响结果。如下程序:
object HelloWorld {
  val a = b+1;
  val b = 5;
  def main(args : Array[String]) {
    println("a:["+a+"]");
    println("b:["+b+"]");
  }
}
/* 结果:
a:[1]
b:[5]
*/


而这个程序:
object HelloWorld2 {
  val b = 5;
  val a = b+1;
  def main(args : Array[String]) {
    println("a:["+a+"]");
    println("b:["+b+"]");
  }
}
/* 输出:
a:[6]
b:[5]
*/


fvzone 2010-04-13
新手来学习了!
Eastsun 2010-04-14
LZ如果把
class A(f: A => Int) { 
  val x = f(this) 
} 

改成
class A(f: A => Int) { 
  lazy val x = f(this) 
} 


你会发现更爽
Global site tag (gtag.js) - Google Analytics