5

Possible Duplicate:
Use of def, val, and var in scala

I'm learning now Scala and I can't modify variable in class.

class Person(name: String, var variable: Int) {
  def change() {
    variable = 42
  }
}
def person = new Person("name", 0)
println(person.variable)
person.change()
println(person.variable)

And the output is:

0
0

Why output contains 2 times 0?

How I can modify variable in this Code?

I have Scala version 2.9.1.

Community
  • 1
  • 1
Marcin Stachniuk
  • 716
  • 7
  • 14
  • See also http://stackoverflow.com/questions/4437373/use-of-def-val-and-var-in-scala/4440614 – Jesper Nov 02 '12 at 08:00

3 Answers3

12

This took me a while to realize as well :)

You are not defining a val or var "person", but creating a new method person. Therefore, every time you you invoke person, it will create a new instance of Person, which will always have its variable set to 0. This is a side effect of the fact that in Scala you don't need the () to invoke parameterless methods.

def person = new Person("foo", 1)

is roughly equivalent to (in Java code)

public Person person() {
    return new Person("foo", 1);
}

whereas val person is what you want, i.e.

Person person = new Person("foo", 1)

(of course that is not a real val because Scala does not support those :))

and when you then use person, what Scala understands is person().

Just change def, which is used for defining methods, to val or var and you'll be fine :)

fresskoma
  • 25,481
  • 10
  • 85
  • 128
6

Wasn't easy to spot! Here:

def person = new Person("name", 0)

you define a method named person. To make it more clear, you do something like this:

def person(): Person = {
  return new Person("name", 0)
}

That means every time you say person you are not referring to a variable but calling a method and creating new instance over and over again.

Just say val person =... and you'll be fine.

Believe it or not, that's actually a feature of the language. E.g. you can create a field (val) in your class, then change your mind and turn it into a getter by simply changing to def. From the client code perspective nothing changes.

Tomasz Nurkiewicz
  • 334,321
  • 69
  • 703
  • 674
0

Let's analyze your code, piece by piece. First you declared a class called person. class Person(name: String, var variable: Int) with 2 parameters, name and variable. Under this class, you have a method called: def change().

and it has a variable with 42 as its value. Then you called the def change() method by person.change()

This person.change() is not actually changing the value of the var variable but is actually calling the method it self. Try doing a println(person.change()) and you will see that it will print "42".

I guess, you still don't understand the difference between class and def. if you want to change the value of class Person, you need a new def to call the change.

 class Person(name: String, var variable: Int) {
  println(variable)
}
def changePerson = Person("new value of name here", "new value of variable here");

Now call the defChangePerson and it will now print the value you passed to it.