I'd start by the distinction that exists in Scala between def, val and var.
def - defines an immutable label for the right side content which is lazily evaluated - evaluate by name.
val - defines an immutable label for the right side content which is eagerly/immediately evaluated - evaluated by value.
var - defines a mutable variable, initially set to the evaluated right side content.
Example, def
scala> def something = 2 + 3 * 4
something: Int
scala> something // now it's evaluated, lazily upon usage
res30: Int = 14
Example, val
scala> val somethingelse = 2 + 3 * 5 // it's evaluated, eagerly upon definition
somethingelse: Int = 17
Example, var
scala> var aVariable = 2 * 3
aVariable: Int = 6
scala> aVariable = 5
aVariable: Int = 5
According to above, labels from def and val cannot be reassigned, and in case of any attempt an error like the below one will be raised:
scala> something = 5 * 6
<console>:8: error: value something_= is not a member of object $iw
something = 5 * 6
^
When the class is defined like:
scala> class Person(val name: String, var age: Int)
defined class Person
and then instantiated with:
scala> def personA = new Person("Tim", 25)
personA: Person
an immutable label is created for that specific instance of Person (i.e. 'personA'). Whenever the mutable field 'age' needs to be modified, such attempt fails:
scala> personA.age = 44
personA.age: Int = 25
as expected, 'age' is part of a non-mutable label. The correct way to work on this consists in using a mutable variable, like in the following example:
scala> var personB = new Person("Matt", 36)
personB: Person = Person@59cd11fe
scala> personB.age = 44
personB.age: Int = 44 // value re-assigned, as expected
as clear, from the mutable variable reference (i.e. 'personB') it is possible to modify the class mutable field 'age'.
I would still stress the fact that everything comes from the above stated difference, that has to be clear in mind of any Scala programmer.