2016-12-15 7 views
1

Intの値がxの2つのクラスを作成するScala REPLで単純なコードを実行しています。デフォルトコンストラクタの引数はどのようにフィールドに変換されますか?

scala> class C(x: Int){} 
defined class C 

scala> new C(100).x 
<console>:13: error: value x is not a member of C 
     new C(100).x 
       ^

scala> class D(val x: Int){} 
defined class D 

scala> new D(100).x 
res1: Int = 100 

私の理解では、クラスCための変数xが変更可能な変数(デフォルトではvar)とクラスDのための不変変数になるだろうということでした。ここでは方法です。しかし、私はxCのメンバーでないこの問題にぶつかりました。

どのようにですか? Scalaのクラスで

答えて

3

この質問を調査するには、リバースエンジニアリング「コンパイラは何をしますか?」を参照してください。 :)そのために

、我々は実行することにより、コンテンツ class C(x: Int){}でクラスC.scalaをコンパイルされています

scalac C.scala

これは、C.classを生成します。 コンパイラが生成する内容を確認するには、java class disassembler javapを使用できます。

javap -p C.class を実行して生成します:

public class C { 
    public C(int); 
} 

を我々は class D(val x: Int){} で全体の手順を繰り返している場合は、我々がもたらすであろう:

public class D { 
    private final int x; 
    public int x(); 
    public D(int); 
} 

を我々は差がキーワードということであることがわかりますvalは、ゲッターメソッドを作成するようにクラスに指示しています。

valキーワードがなければ、クラス変数は可変であると定義されます。これは間違っています。私たちが分解を深く理解できることを証明するために。実行することにより:

{ 
    public C(int); 
    descriptor: (I)V 
    flags: ACC_PUBLIC 
    Code: 
     stack=1, locals=2, args_size=2 
     0: aload_0 
     1: invokespecial #14     // Method java/lang/Object."<init>":()V 
     4: return 
     LocalVariableTable: 
     Start Length Slot Name Signature 
      0  5  0 this LC; 
      0  5  1  x I 
     LineNumberTable: 
     line 4: 0 
     line 2: 4 
    MethodParameters: 
     Name       Flags 
     x        final 
} 

あなたは変数xクラスはまだfinalとして宣言ので、不変であることをはっきりと見ることができます。

javap -p -v C.class

を我々は(他の多くの情報の中で)このスニペットを取得します。

1

属性は以下の修飾子を持つことができます。

  • valは属性が不変になります。それは、常に公共ません - 値が
  • varを変更することはできませんので、これは理にかなっている属性が変更可能と公共なり
  • 何の修飾子属性が変更可能とプライベートになり

コード例:

// no modifier 
class A(x: Int) { 
    def print() = { 
    x += 1 // this i fine, it's mutable 
    println(x) 
    } 
} 

val a = new A(3) 
// a.x - compile error, it's private 


// var 
class A(var x: Int) { 
    def print() = { 
    x += 1 // this is fine, it's mutable 
    println(x) 
    } 
} 

    val a = new A(3) 
    a.x // you can do this since it's public (modifier var) 

// val 
class A(val x: Int) { 
    def print() = { 
    // x += 1 // can't do this, it's immutable 
    println(x) 
    } 
} 

val a = new A(3) 
a.x // you can do this since it's public (modifier val) 

コンストラクタとクラスの詳細:http://joelabrahamsson.com/learning-scala-part-four-classes-and-constructors/

+2

最初の段落の3つの主張はすべて間違っています: 'val'と' var'は必ずしもpublicではなく、単にデフォルトです。修飾子を使用しない場合は、フィールドがある場合とない場合があります(パラメータがどのメソッドでも使用されているかどうかによって異なります)。 –

+0

私は彼らがいつも公開されているわけではないことに同意します。 'private'を修正して使うこともできますが、答えのポイントはまだ残っていると思います。この場合、デフォルトで公開されています。私は答えを編集することができます。私は提案を編集するために開いています。方法については、私は完全にそれを理解しているか分からない。 'class A(val t:Int)'のようなものを使用し、 't'がクラスの属性/フィールドになる例は何ですか? –

+0

'クラスA(i:Int)'を持つとき、クラス 'A'は' i'のためのフィールドを持ちません。 'i'は単なる(不変の)コンストラクタパラメータです。あなたが 'class A(i:Int){def foo = i}'を持つとき、クラス 'A'は' i'のための私有の不変フィールドを持っています。 –

関連する問題