135

努力しています:

class Foo(bar: Int)

対:

class Foo(private val bar: Int)

(bar: Int)そして、それらは同じように動作しているように見えますが、それが拡張されていると言っている場所がどこにも見つからなかった(private val bar: Int)ので、私の質問は、これらは同一/類似ですか?

余談ですが、私は-Xprint:typerこれらのコード部分で使用しようとしてきましたが、2 番目の行に余分な行があることを除いて、同じコードを生成します。その余分な行をどのように読むのですか?

..
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、プライベートゲッターを使用してフィールドが作成されます。この動作は、パラメーターがコンストラクターの横で使用されたかどうかに関係なく、上記と同じです(たとえば、intoString()かどうか)。

val bar: Int

上記と同じですが、Scalaのようなゲッターは公開されています

bar: Intケースクラスの場合

ケースクラスが含まれる場合、デフォルトでは、各パラメーターにval修飾子があります。

于 2013-02-04T20:17:39.913 に答える
108

最初のケースでbarは、コンストラクタ パラメータのみです。メインコンストラクターはクラス自体のコンテンツであるため、その中でアクセスできますが、このインスタンスからのみアクセスできます。したがって、次とほぼ同等です。

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

一方、2 番目のケース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 に答える