在玩Scala时,我有这样的代码:
class Superclass(var i : Int){}
class Subclass(i : Int) extends Superclass(0) {
print(i)
}
我发现print(i)
打印构造函数参数i
Subclass(i : Int)
现在,我的问题是:在这种情况下,我如何访问Superclass
的现场i
?
类型归属可以向上转换this
的类型,从而有效地消除两个标识符的歧义
class Subclass(i : Int) extends Superclass(0) {
print((this: Superclass).i)
print(i)
}
作为旁注,还存在以下语法,可用于方法成员(可能并不为人所知(
super[ClassQualifier]
例如,请考虑以下事项
trait A {
def f = "A"
}
trait B extends A {
override def f = "B"
}
class C extends A with B {
println(super[A].f)
println(super[B].f)
println(f)
override def f = "C"
}
new C
// A
// B
// C
@MarioGalic回答了这个问题。我只想做一些太长而无法评论的补充。
常见的误解是i
class MyClass(i : Int)
只是一个构造函数参数,而不是一个字段。其实如果我们这样做
import scala.reflect.runtime.universe._
println(reify{
class MyClass(i : Int)
}.tree)
我们拭目以待(Scala 2.13.2(
{
class MyClass extends AnyRef {
<paramaccessor> private[this] val i: Int = _;
def <init>(i: Int) = {
super.<init>();
()
}
};
()
}
因此,没有val
/var
的主构造函数的参数会生成private[this]
字段。所以
class MyClass(i : Int)
类似于
class MyClass(private[this] val i : Int)
并且与Java的不相似
public class MyClass {
public MyClass(int i) {
}
}
没有字段。
我们可以检查i
是否是一个引用它的字段,this
类主体
class MyClass(i : Int) {
println(this.i)
}
new MyClass(1) // prints 1
字段i
是private[this]
的,所以我们不能在类主体之外(或与this
不同的实例的主体内部(引用它
class MyClass(i : Int) {
//println(new MyClass(2).i) //doesn't compile
}
//new MyClass(1).i //doesn't compile
我在 Scala 规范中没有找到合适的位置,但这种行为早已为人所知。例如,在Cay S. Horstmann的"Scala for the impatient"中写道(第2版,第5.7节(:
施工参数也可以是常规方法参数,无需
val
或var
。如何处理这些参数取决于它们在类中的用法。
如果在至少一个方法中使用不带
val
或var
的参数,则该参数将成为字段。例如class Person(name: String, age: Int) { def description = name + " is " + age + " years old" }
声明和初始化对象私有
name
和age
的不可变字段。这样的字段等同于private[this] val
字段(请参见第 56 页的第 5.4 节 "对象私有字段"(。否则,参数不会另存为字段。它只是一个可以在主构造函数的代码中访问的常规参数。(严格来说,这是特定于实现的优化。
实际上在 2.13.2 中我无法确认第二种情况。
现在让我们有两个类。
斯卡拉不允许
class Superclass {
val i: Int = 1
}
class Subclass extends Superclass {
//val i: Int = 2 //doesn't compile
}
除非我们添加override
class Superclass {
val i: Int = 1
}
class Subclass extends Superclass {
override val i: Int = 2
}
但如果Superclass
的领域是private[this]
那么没有override
一切都好
class Superclass {
private[this] val i: Int = 1
}
class Subclass extends Superclass {
val i: Int = 2
}
实际上,如果我们尝试添加override
则无法编译。
原因是这不是覆盖。其中一个字段是private[this]
即在定义字段的对象之外无法访问,因此这只是两个不同的字段:
class Superclass {
private[this] val i: Int = 1
}
class Subclass extends Superclass {
val i: Int = 2
println(this.i) // or just println(i)
// println((this: Superclass).i) //doesn't compile
}
new Subclass
//2
或
class Superclass {
val i: Int = 1
}
class Subclass extends Superclass {
private[this] val i: Int = 2
println(this.i) // or just println(i)
println((this: Superclass).i)
}
new Subclass
//2
//1
所以在我们的例子中
class Superclass(var i : Int)
class Subclass(i : Int) extends Superclass(0)
就像
class Superclass extends AnyRef {
var i: Int = _
def this(_i: Int) = {
super() //pseudocode
i = _i
}
}
class Subclass extends Superclass {
private[this] val i: Int = _ //pseudocode
def this(_i: Int) = {
super(0) //pseudocode
i = _i //pseudocode because "i" is a val -- well, compiler can do things that we can't do in source code
}
}
内部Subclass
this.i
或简称i
指Subclass
的场private[this] val i: Int
,(this: Superclass).i
指Superclass
的场var i: Int
。
scala 构造函数参数默认为私有 val 吗?
Scala 构造函数参数
https://www.scala-lang.org/old/node/8384.html