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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14694712/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 04:55:19  来源:igfitidea点击:

Do scala constructor parameters default to private val?

scalascala-primary-constructor

提问by none

I have been trying:

我已经试了:

class Foo(bar: Int)

vs:

对比:

class Foo(private val bar: Int)

and they seem to behave the same although I couldn't find anywhere saying that (bar: Int)expands to (private val bar: Int)so my question is, are these identical/similar?

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

On a side note, I have been trying to use -Xprint:typeron these code pieces and they produce the same code except for an extra line in the second one. How do I read that extra line?

附带说明一下,我一直在尝试使用-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>();
    ()
  }
}
..

回答by Tomasz Nurkiewicz

bar: Int

bar: Int

This is barely a constructor parameter. If this variable is not used anywhere except the constructor, it remains there. No field is generated. Otherwise private val barfield is created and value of barparameter is assigned to it. No getter is created.

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

private val bar: Int

private val bar: Int

Such declaration of parameter will create private val barfield with private getter. This behavior is the same as above no matter if the parameter was used beside the constructor (e.g. in toString()or not).

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

val bar: Int

val bar: Int

Same as above but Scala-like getter is public

同上,但类 Scala 的 getter 是公开的

bar: Intin case classes

bar: Int以防万一

When case classes are involved, by default each parameter has valmodifier.

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

回答by gourlaysama

In the first case, baris only a constructor parameter. Since the main constructor is the content of the class itself, it is accessible in it, but only from this very instance. So it is almost equivalent to:

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

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

On the other hand, in the second case baris a normalprivate field, so it is accessible to this instance andother instances of Foo. For example, this compiles fine:

另一方面,在第二种情况下bar是一个普通的私有字段,所以它可以被这个实例其他实例访问Foo。例如,这编译得很好:

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

And runs:

并运行:

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

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

But this doesn't:

但这不会:

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