我正在通过Scala处理超类构造函数来体验一种奇怪的行为。
我有一个非常简单的类,按以下方式定义
package server
class Content(identifier:String,content:String){
def getIdentifier() : String = {identifier}
def getContent() : String = {content}
}
和一个简单的子类
package server
class SubContent(identifier:String, content:String) extends Content(identifier, content+"XXX")){
override def getContent():String = {
println(content)
super.getContent
}
}
真正奇怪的是,在子类中有超类属性的重复,所以如果我创建一个新对象
var c = new SubContent("x","x")
执行
c.getContent
首先输出“x”(提供给子类构造函数的值),但返回“xXXX”(提供给超类构造函数的值)。
有没有办法避免这种行为?基本上我想要的是子类不创建自己的属性,而只是将参数传递给超类。
答案 0 :(得分:8)
这正是你告诉它要做的事情。在将第二个构造函数传递给超类构造函数时,您将其扩充,然后使用超类“getContent
提供从子类”getContent
返回的值。
您需要注意的是构造函数参数(那些与属性无关,因为它们属于case class
或因为它们是使用val
关键字声明的)属于范围整个班级的身体。类的构造函数是其正文在之外的任何方法的一部分。因此,对方法体中构造函数参数的引用会强制构造函数参数存储在字段中,以便它可以具有必要的范围。请注意,println
中的getContent
调用会导致此类隐藏的构造函数参数字段。
回复评论“是否有另一种方法来定义它以避免这种情况?或者至少,如果我从未参考子类构造函数的参数,则会分配它们的字段(浪费存储器)“:
如果对构造函数参数(*)的唯一引用在构造函数中是正确的(即,在任何方法体之外,并且val
和var
初始值设定项不符合方法体),则不将创建不可见字段以保存构造函数参数。
然而,如果你试图“避免”这些不可避免的领域,我不明白你在问什么。
(*)“普通构造函数参数”是指不属于案例类且不带val
关键字的那些参数。