51

違いは何ですか:

class Person(name: String, age: Int) {
  def say = "My name is " + name + ", age " + age
}

class Person(val name: String, val age: Int) { 
  def say = "My name is " + name + ", age " + age
}

varパラメータをsとして宣言し、後でそれらの値を変更できますか?例えば、

class Person(var name: String, var age: Int) {

  age = happyBirthday(5)

  def happyBirthday(n: Int) {
    println("happy " + n + " birthday")
    n
  }
}
4

6 に答える 6

51

最初の部分の答えはスコープです:

scala> class Person(name: String, age: Int) {
     |   def say = "My name is " + name + ", age " + age
     | }

scala> val x = new Person("Hitman", 40)

scala> x.name
<console>:10: error: value name is not a member of Person
              x.name

上記のコードでわかるように、パラメータの前に。を付けるとval、クラスの外部から表示されます。そうでない場合は、プライベートになります。var

はい、通常どおり、変数の値を変更できます。

于 2013-03-26T14:08:58.537 に答える
10

これ

class Person(val name: String, val age: Int)

クラスのユーザーがフィールドを外部で利用できるようにします。たとえば、後で実行できます。

val p = new Person("Bob", 23)
val n = p.name

argsをvar、として指定した場合、スコープはの場合と同じですvalが、フィールドは変更可能です。

于 2013-03-26T14:08:32.783 に答える
9

Javaに精通している場合は、次の例からアイデアを得ることができます。

class Person(name: String, age: Int)

に似ています

class Person {
  public Person(String name, int age) {
  }
}

その間

class Person(var name: String, var age: Int) // also we can use 'val'

と類似しています

class Person {
  String name;
  int age;

  public Person(String name, int age) {
     this.name = name;
     this.age = age;
  }
}

直感的には、var / valがないと、変数はコンストラクター内でのみアクセスできます。var / valが追加された場合、クラスには同じ名前のメンバー変数が含まれます。

于 2014-11-23T22:39:33.403 に答える
2

ここでの答えは本当に良いですが、私はバイトコードを調べてこれに取り組んでいます。クラスに適用するjavapと、渡されたクラスのパッケージ、保護、およびパブリックフィールドとメソッドが出力されます。Person.scalaクラスを作成し、次のコードを入力しました。

class Person(name: String, age: Int) {
  def say = "My name is " + name + ", age " + age
}

class PersonVal(val name: String, val age: Int) {
  def say = "My name is " + name + ", age " + age
}

class PersonVar(var name: String, var age: Int) {

  age = happyBirthday(5)

  def happyBirthday(n: Int) = {
    println("happy " + n + " birthday")
    n
  }
}

コードをコンパイルするscalac Person.scalaと、名前が付いた3つのファイルが生成されますPerson.class, PersonVal.calass , PersonVar.cassjavapこれらのクラスファイルごとに実行することで、構造がどのようになるかを確認できます。

>>javap Person.class
Compiled from "Person.scala"
public class Person {
  public java.lang.String say();
  public Person(java.lang.String, int);
}

この場合、valでもvalでも宣言されていないため、Personのクラス変数は作成されませんでした。したがって、nameとageはコンストラクター内で使用できます。

>>javap PersonVal.class
public class PersonVal {
  public java.lang.String name();
  public int age();
  public java.lang.String say();
  public PersonVal(java.lang.String, int);
}

この場合、入力コンストラクター用に2つ、コンストラクター内で宣言したメンバー用に1つ、3つのメンバーがあります。ただし、入力コンストラクターのセッターがないため、値を変更できません。

>>javap PersonVar.class
public class PersonVar {
  public java.lang.String name();
  public void name_$eq(java.lang.String);
  public int age();
  public void age_$eq(int);
  public int happyBirthday(int);
  public PersonVar(java.lang.String, int);
}

PersonValの例と同じですが、この場合、これらのvariable_$eqメソッドを使用して値を変更できます。それは単なる短縮版ではありませんvariable =

于 2017-10-16T15:54:20.393 に答える
0

を使用できますcase class。その場合、Personクラスはクラスの外部でそれらの変数を使用できます。 case class Person(name: String, age: Int)。そうすると、次のコードは期待どおりに機能します。val z = new Person("John", 20); z.name //John

于 2016-04-12T19:02:07.677 に答える
0

著者がjavapを使用してバイトコードを調査する@Rezaの回答は、この概念を最もよく明確にするのに役立ちました。このケースの非常に具体的な例を引用するには、本番Webアプリ(Play + Scala)で直面した以下のシナリオを参照してください:Scala のクラス/トレイトメソッドにパラメーターを挿入する方法

注入されたパラメーターにvalプレフィックスを使用しない場合authorizationHandler、コンパイラーは次のエラーをスローします。

class MyController needs to be abstract, since method authorizationHandler in trait AuthorizationCheck of type => controllers.authapi.AuthorizationHandler is not defined
[error] class MyController @Inject() (authorizationHandler: AuthorizationHandler) extends Controller with AuthorizationCheck {
[error]       ^
[error] one error found

残念ながら、このエラーは、プレフィックスの前にある正しい問題を特定するのに役立ちませんでしたval

class MyController @Inject()(val authorizationHandler: AuthorizationHandler) extends Controller with AuthorizationCheck {

   def myAction = AuthenticatedAction { implicit request =>
     ...
   }
} 
于 2018-03-02T07:12:40.273 に答える