关于scala中抽象类型类的初始化问题
我定义了一个具有抽象类型的类,如下所示:
abstract class AbsCell2{
type T
val init: T
private var value: T = {
println("Hello "+init);
init
}
def get : T = value
def set(x : T) = { value = x}
}
现在我实例化一个 Int 类型的对象
scala> val cell = new AbsCell2{type T = Int ; val init = 10}
Hello 0
cell: AbsCell2{type T = Int} = $anon$1@969ebb
请注意 println
的输出。看来变量init
还没有被初始化为10。注意scala的版本是2.9.0-1
I define a class with abstract type as follow:
abstract class AbsCell2{
type T
val init: T
private var value: T = {
println("Hello "+init);
init
}
def get : T = value
def set(x : T) = { value = x}
}
Now I instantiate an object with type Int
scala> val cell = new AbsCell2{type T = Int ; val init = 10}
Hello 0
cell: AbsCell2{type T = Int} = $anon$1@969ebb
Pay attention to the output from println
. It seams the variable init
hasn't been initialized as 10. Note that the version of scala is 2.9.0-1
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我认为您正在寻找 Scala 的 早期初始化器,
早期初始化器允许您分配一个新对象并在之前设置一些特定字段类构造函数运行。在本例中,由于
value
取决于init
,因此我们使用早期初始化语法(new { val init = ... } with AbsCell2
)首先设置init
,以便类构造函数可以正确初始化value
。另请参阅这个问题:在 Scala 中,什么是“早期初始化器”?
I think you're looking for Scala's early initializers,
Early initializers allow you to allocate a new object and set some specific fields before the class constructor runs. In this case, since
value
depends oninit
, we use the early initializer syntax (new { val init = ... } with AbsCell2
) to first setinit
so that the class constructor can properly initializevalue
.See also this question: In Scala, what is an "early initializer"?
从 val 更改为 def:
它按预期工作:
Change from val to def:
It works as expected:
对于有关
new { type T = Int ; 之间差异的问题val init = 10 }
with AbsCell2 和new AbsCell2 { type T = Int ; val init = 10 }
。第一个是所谓的早期初始化器或预初始化字段(在《Scala 编程》中的“抽象成员”章节中提到)。它允许子类在超类之前初始化字段。叫。
在这种情况下,init在AbsCell2初始化之前就已经被设置为10了。
后一种是正常继承,它创建一个匿名类,然后扩展AbsCell2,就像:
但是,匿名类是在抽象类AbsCell2之后初始化的,所以init 在自身初始化时不可用,即 init 是 Type 的默认值,本例中为 0。因此,你在打印中得到0。
使用
scalac -Xprint:all Test.scala
,你会看到以下内容:从代码中我们可以看到,对于正常的初始化,init之后被设置为3超类AbsCell2的初始化,当AbsCell2.this.init()被调用时,它实际上引用了子类的init字段,并且3还没有设置,所以我们得到默认的类型值。相反,早期初始化首先设置初始化到3.然后调用超类初始化。
For question about difference between
new { type T = Int ; val init = 10 }
with AbsCell2 andnew AbsCell2 { type T = Int ; val init = 10 }
。The first one is the so-called early-initializers or pre-initialized fields(mentioned in Abstract Members chapter in Programming In Scala)。It allows the subclass to initialize fields before the super class is called。
In this case, init has already been set as 10 before the initialization of AbsCell2。
The latter one is normal inheritance, it creates an anonymous class then extends AbsCell2, just like:
However, the anonymous class gets initialized after the abstract class AbsCell2, so init are not available in the initialization of itself, namely, init is the default value of the Type, 0 in this case. Therefore, you get 0 in the print。
use
scalac -Xprint:all Test.scala
, you will see the following:From the code, we can see that for normal initialization, init is set to 3 after the initialization of super class AbsCell2, when AbsCell2.this.init() gets invoked, it actually refers to the subclass' init field and 3 is yet to set, so we get the default type value。On the contrary, early initialization first set init to 3 then call super class initialization。