Scala构造函数参数默认为private val吗?


128

我已经试了:

class Foo(bar: Int)

vs:

class Foo(private val bar: Int)

他们似乎有同样的表现,虽然我无法找到任何地方说,(bar: Int)扩张到(private val bar: Int),所以我的问题是,这些相同/相似?

顺便说一句,我一直试图-Xprint:typer在这些代码段上使用,它们产生相同的代码,除了第二行中的额外一行。我如何阅读多余的文字?

..
class Foo extends scala.AnyRef {
  <paramaccessor> private[this] val bar: Int = _;
  def <init>(bar: Int): this.Foo = {
    Foo.super.<init>();
    ()
  }
}
..


..
class Foo extends scala.AnyRef {
  <paramaccessor> private[this] val bar: Int = _;
  <stable> <accessor> <paramaccessor> private def bar: Int = Foo.this.bar;
  def <init>(bar: Int): this.Foo = {
    Foo.super.<init>();
    ()
  }
}
..

Answers:


177

bar: Int

这几乎不是构造函数参数。如果未在构造函数以外的任何地方使用此变量,则它将保留在该变量中。没有生成任何字段。否则,private val bar将创建字段并bar为其分配参数值。没有创建吸气剂。

private val bar: Int

此类参数声明将private val bar使用私有getter 创建字段。无论是否在构造函数旁边使用了参数(例如,是否在构造函数中toString()),此行为都与上面相同。

val bar: Int

与上面相同,但是类似Scala的getter是公开的

bar: Int 情况分类

当涉及案例类时,默认情况下,每个参数都有val修饰符。


15
在类的情况下,所有参数都将变为“ public” val
drexin

6
天哪,我不时戴眼镜,但这太多了。
om-nom-nom

1
@ om-nom-nom:对不起,我不明白。我是否应该改善格式/结构以使其更具可读性?
Tomasz Nurkiewicz

1
@TomaszNurkiewicz:var可用于将构造函数参数呈现给非类casecase类中的(可变)类属性,并且有意义。
兰德尔·舒尔茨

8
在“斯卡拉不耐烦的书编写的bar: Int编译private[this] val bar: Int
MyTitle

98

在第一种情况下,bar仅是构造函数参数。由于主要的构造函数是类本身的内容,因此只能在该实例中访问它。因此,它几乎等同于:

class Foo(private[this] val bar:Int)

另一方面,在第二种情况下,bar是一个普通的私有字段,因此该实例和的其他实例均可访问Foo。例如,这可以正常编译:

class Foo(private val bar: Int) {
  def otherBar(f: Foo) {
    println(f.bar) // access bar of another foo
  }
}

并运行:

scala> val a = new Foo(1)
a: Foo = Foo@7a99d0af

scala> a.otherBar(new Foo(3))
3

但这不是:

class Foo(bar: Int) {
  def otherBar(f: Foo) {
    println(f.bar) // error! cannot access bar of another foo
  }
}

9
这是比公认的更好的答案;它突出了裸bar: Int和裸之间的区别private val ...
hraban
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.