135

我已经试了:

class Foo(bar: Int)

与:

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>();
    ()
  }
}
..
4

2 回答 2

184

bar: Int

这几乎不是构造函数参数。如果除了构造函数之外没有在任何地方使用这个变量,它就会保留在那里。不生成任何字段。否则private val bar,将创建字段并bar为其分配参数值。没有创建吸气剂。

private val bar: Int

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

val bar: Int

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

bar: Int在案例类

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

于 2013-02-04T20:17:39.913 回答
108

在第一种情况下,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
  }
}
于 2013-02-04T20:19:26.150 回答