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

non*_*one 119 scala scala-primary-constructor

我已经试了:

class Foo(bar: Int)
Run Code Online (Sandbox Code Playgroud)

VS:

class Foo(private val bar: Int)
Run Code Online (Sandbox Code Playgroud)

而且他们似乎表现得一样,虽然我找不到任何地方说(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>();
    ()
  }
}
..
Run Code Online (Sandbox Code Playgroud)

Tom*_*icz 168

bar: Int

这几乎不是构造函数参数.如果除了构造函数之外没有使用此变量,它仍然存在.没有生成字段.否则private val bar创建字段并bar为其分配参数值.没有创建getter.

private val bar: Int

这样的参数声明将创建private val bar具有私有getter的字段.无论参数是否在构造函数旁边使用(例如,是否toString()存在),此行为与上述相同.

val bar: Int

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

bar: Int 在案例类

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

  • 在类的情况下,所有参数都将变为"public"`val`. (15认同)
  • 在'Scala for the Impatient'一书中写道:`bar:Int`编译为`private [this] val bar:Int` (7认同)
  • 天哪,我不时戴眼镜,但这太过分了. (5认同)

gou*_*ama 89

在第一种情况下,bar只是一个构造函数参数.由于主构造函数是类本身的内容,因此可以在其中访问它,但仅限于此实例.所以它几乎相当于:

class Foo(private[this] val bar:Int)
Run Code Online (Sandbox Code Playgroud)

另一方面,在第二种情况下bar普通的私有字段,因此该实例其他实例可以访问它Foo.例如,这编译好:

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

并运行:

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

scala> a.otherBar(new Foo(3))
3
Run Code Online (Sandbox Code Playgroud)

但这不是:

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

  • 这是一个比被接受的答案更好的答案; 它突出了裸`bar:Int`和`private val ...`之间的区别. (4认同)