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 . 如果我使用var或val,则输出为 20
. 我理解scala中的默认值是val . 这个:
def age = 30
age = 45
...给出编译错误,因为它默认为val . 为什么上面的第一组行不能正常工作,而且还没有错误?
6 回答
在Scala中有三种定义方法:
def
定义 methodval
定义了一个固定的 value (不能修改)var
定义 variable (可以修改)看看你的代码:
这定义了一个名为
person
的新方法 . 您只能在没有()
的情况下调用此方法,因为它被定义为无参数方法 . 对于empty-paren方法,您可以使用或不使用'()'来调用它 . 如果你只是写:那么你正在调用这个方法(如果你没有分配返回值,它将被丢弃) . 在这行代码中:
会发生什么是您首先调用
person
方法,并在返回值(类Person
的实例)上更改age
成员变量 .最后一行:
在这里,您再次调用
person
方法,该方法返回类Person
的新实例(age
设置为12) . 它与此相同:我将从 def , val 和 var 之间的Scala中存在的区别开始 .
def - 为右侧内容定义不可变标签 lazily evaluated - 按名称评估 .
val - 为右侧内容定义不可变标签_11101515_ - 按值评估 .
var - 定义一个可变变量,最初设置为评估的右侧内容 .
Example, def
Example, val
Example, var
根据以上所述, def 和 val 中的标签无法重新分配,如果有任何尝试,将引发如下所示的错误:
当类被定义为:
然后实例化:
为该特定Person实例创建 immutable label (即'personA') . 每当需要修改可变字段'age'时,此类尝试将失败:
正如预期的那样,'年龄'是不可变标签的一部分 . 处理此问题的正确方法包括使用可变变量,如下例所示:
同样清楚,从可变变量引用(即'personB')可以修改类可变字段'age' .
我仍然会强调,所有内容都来自上述差异,任何Scala程序员都必须清楚这一点 .
同
你正在定义一个函数/惰性变量,它总是返回一个名为“Kumar”且年龄为12的新Person实例 . 这是完全有效的,编译器没有理由抱怨 . 调用person.age将返回此新创建的Person实例的年龄,该实例始终为12 .
写作时
您为类Person中的age属性分配一个新值,该值有效,因为age被声明为
var
. 如果您尝试使用新的Person对象重新分配person
,编译器会抱怨为了提供另一个视角,Scala中的"def"表示每次使用时都要评估的内容,而val是立即评估的内容 . 这里,表达式
def person = new Person("Kumar",12)
需要每当我们使用"person"时,我们将得到一个new Person("Kumar",12)
调用 . 因此,两个"person.age"是无关的,这是很自然的 .这是我理解Scala的方式(可能是以更“功能”的方式) . 我不确定
实际上是斯卡拉的意思 . 我真的不喜欢这样思考至少......
正如金太郎所说,人是一种方法(因为def)并且总是返回一个新的Person实例 . 如您发现,如果将方法更改为var或val,它将起作用:
另一种可能性是:
但是,当您从
person
方法返回Person
实例时,允许在您的代码中使用person.age=20
,并且在此实例中,您可以更改var
的值 . 问题是,在那一行之后你没有更多的引用那个实例(就像每一个调用person
将生成一个新实例) .这没什么特别的,你在Java中会有完全相同的行为:
我们来看看:
并用等效代码重写它
请参阅
def
是一种方法 . 它将在每次调用时执行,并且每次它将返回(a)new Person("Kumar", 12)
. 这些在"assignment"中没有错误,因为它实际上不是一个赋值,而只是调用age_=
方法(由var
提供) .