[英]Use of def, val, and var in scala
class Person(val name:String,var age:Int )
def person = new Person("Kumar",12)
person.age = 20
println(person.age)
这些代码行输出12
,即使person.age=20
已成功执行。 我发现这是因为我在def person = new Person("Kumar",12)
使用了def person = new Person("Kumar",12)
。 如果我使用var或val,则输出为20
。 我理解scala中的默认值是val。 这个:
def age = 30
age = 45
...给出编译错误,因为它默认为val。 为什么上面的第一组行不能正常工作,而且还没有错误?
在Scala中有三种定义方法:
def
定义了一种方法 val
定义一个固定值 (不能修改) var
定义一个变量 (可以修改) 看看你的代码:
def person = new Person("Kumar",12)
这定义了一个名为person
的新方法。 只能在没有()
情况下调用此方法,因为它被定义为无参数方法。 对于empty-paren方法,你可以使用或不使用'()'来调用它。 如果你只是写:
person
那么你正在调用这个方法(如果你没有分配返回值,它将被丢弃)。 在这行代码中:
person.age = 20
所发生的是你首先调用person
方法,并在返回值(类Person
的实例)上更改age
成员变量。
最后一行:
println(person.age)
在这里,您再次调用person
方法,该方法返回类Person
的新实例( age
设置为12)。 它与此相同:
println(person().age)
我首先介绍了def , val和var之间Scala中存在的区别。
def - 为懒惰评估的右侧内容定义不可变标签 - 按名称评估。
val - 为急剧/立即评估的右侧内容定义不可变标签 - 按值评估。
var - 定义一个可变变量 ,最初设置为评估的右侧内容。
例如,def
scala> def something = 2 + 3 * 4
something: Int
scala> something // now it's evaluated, lazily upon usage
res30: Int = 14
例如,val
scala> val somethingelse = 2 + 3 * 5 // it's evaluated, eagerly upon definition
somethingelse: Int = 17
例子,var
scala> var aVariable = 2 * 3
aVariable: Int = 6
scala> aVariable = 5
aVariable: Int = 5
根据上面的说法, def和val的标签不能重新分配,如果有任何尝试,将引发如下所示的错误:
scala> something = 5 * 6
<console>:8: error: value something_= is not a member of object $iw
something = 5 * 6
^
当类被定义为:
scala> class Person(val name: String, var age: Int)
defined class Person
然后实例化:
scala> def personA = new Person("Tim", 25)
personA: Person
为Person的特定实例(即'personA')创建不可变标签 。 每当需要修改可变字段'age'时,此类尝试将失败:
scala> personA.age = 44
personA.age: Int = 25
正如预期的那样,'年龄'是不可变标签的一部分。 处理此问题的正确方法包括使用可变变量,如下例所示:
scala> var personB = new Person("Matt", 36)
personB: Person = Person@59cd11fe
scala> personB.age = 44
personB.age: Int = 44 // value re-assigned, as expected
很明显,从可变变量引用 (即'personB')可以修改类可变字段'age'。
我仍然会强调,所有内容都来自上述差异,任何Scala程序员都必须清楚这一点。
同
def person = new Person("Kumar", 12)
你正在定义一个函数/惰性变量,它总是返回一个名为“Kumar”且年龄为12的新Person实例。这是完全有效的,编译器没有理由抱怨。 调用person.age将返回此新创建的Person实例的年龄,该实例始终为12。
写作时
person.age = 45
您为类Person中的age属性分配一个新值,该值有效,因为age声明为var
。 如果您尝试使用新的Person对象重新分配person
,编译器会抱怨
person = new Person("Steve", 13) // Error
为了提供另一个视角,Scala中的“def”表示每次使用时都要评估的内容,而val是立即评估并且只评估一次的内容 。 这里,表达def person = new Person("Kumar",12)
需要每当我们使用“person”时,我们将获得一个new Person("Kumar",12)
调用。 因此,两个“person.age”是无关的,这是很自然的。
这是我理解Scala的方式(可能是以更“功能”的方式)。 我不确定
def defines a method
val defines a fixed value (which cannot be modified)
var defines a variable (which can be modified)
实际上是斯卡拉的意思。 我真的不喜欢这样思考至少......
正如金太郎所说,人是一种方法(因为def)并且总是返回一个新的Person实例。 如您发现,如果将方法更改为var或val,它将起作用:
val person = new Person("Kumar",12)
另一种可能性是:
def person = new Person("Kumar",12)
val p = person
p.age=20
println(p.age)
但是,当您从person
方法返回Person
实例时,允许在您的代码中使用person.age=20
,并且在此实例上,您可以更改var
的值。 问题是,在那一行之后你没有更多的引用那个实例(因为每次调用person
都会产生一个新的实例)。
这没什么特别的,你在Java中会有完全相同的行为:
class Person{
public int age;
private String name;
public Person(String name; int age) {
this.name = name;
this.age = age;
}
public String name(){ return name; }
}
public Person person() {
return new Person("Kumar", 12);
}
person().age = 20;
System.out.println(person().age); //--> 12
我们来看看:
class Person(val name:String,var age:Int )
def person =new Person("Kumar",12)
person.age=20
println(person.age)
并用等效代码重写它
class Person(val name:String,var age:Int )
def person =new Person("Kumar",12)
(new Person("Kumar", 12)).age_=(20)
println((new Person("Kumar", 12)).age)
看, def
是一种方法。 它将在每次调用时执行,并且每次它将返回(a) new Person("Kumar", 12)
。 这些在“赋值”中没有错误,因为它实际上不是赋值,而只是调用age_=
方法(由var
提供)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.