Scala类的构造函数参数

有什么区别:

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 } } 

第一部分的答案是范围:

 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 

如果你用valvar作为参数的前缀,它们将在类的外部可见,否则它们将是私有的,就像你在上面的代码中看到的那样。

是的,你可以改变var的值,就像平常一样。

这个

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

使得这些字段可以在外部提供给这个类的用户,例如你稍后可以做到

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

如果将参数指定为var ,那么作用域与val相同,但是这些字段是可变的。

如果你熟悉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,variables只能在构造函数中访问。 如果添加了var / val,那么类将具有相同名称的成员variables。

你可以使用一个case class ,在这种情况下, Person类可以在类之外提供这些variables。 case class Person(name: String, age: Int) 。 然后下面的代码将按预期工作。 val z = new Person("John", 20); z.name //John

这里的答案是非常好的,但是我正在研究这个字节码。 当你在一个类上应用javap时,它会打印出传递的类的包,保护和公共字段和方法。 我创build了一个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编译代码后,它会生成三个名称分别为Person.class, PersonVal.calass , PersonVar.cass 。 通过为每个这些类文件运行javap ,我们可以看到结构如何:

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

在这种情况下,它没有为Person创build任何类variables,因为它既不是val也不是val,所以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); } 

在这种情况下,它有三个成员两个用于input构造函数,另一个用于构造函数中声明的成员。 然而,我们没有任何input构造函数的setter,所以我们不能改变这些值。

 >>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 =的缩写版本