scala – 当超越一个特质,为什么这个价值是奇怪的?
演示
scala代码:
trait A { val a = 3 val b = a + 2 } trait B extends A { override val a = 10 } object X extends B println(X.b) 它打印值:2,为什么不是5或12? 解决方法
回答为什么:
写在Scala时 class A { val a = 2 } 该值在类的构造函数中初始化(同样的行为适用于特征和对象).此外,超类在子类之前初始化.这为您的用例导致以下行为: B被创建(内存被保留),其中两个变量a和b的值为0.现在调用A的构造函数.因为a在子类中被覆盖,并且由于Scalas动态绑定性质,它不分配2,而是分配了子类的值.你想要成为10,但是由于此分配发生在B的构造函数(尚未被调用)中,所以分配默认值0.现在,b被分配.因为它不被覆盖,所以选择值a 2,其中a为0.因为A的构造函数在此完成,所以可以调用B的构造函数,它将10分配给a. 因此,a为10,b为2. 回答这个行为的错误: 只要您不能完全了解可能出现的问题,请勿使用阀门.使用defs或lazy vals而不是在类的构造函数中初始化值,因此可以轻易地覆盖.如果你绝对需要一个特征的val,那么做最后的 可以将var标记为独立于子类的初始化,可以使用var a:Type = _完成.这告诉编译器不要在定义类的构造函数中初始化此变量(但是意味着该值需要保持可变).它可以很容易地在子类中分配.当调用超类作为方法的构造函数时,这会很重要,初始化一个var: class A { f() def f() = () } class B extends A { // don't initialize this var with anything else here or // the later assignment will be overwritten var b: Int = _ override def f() = b = 5 } new B().b // prints 5 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |