The answers here are really good, however I'm tackling this one with exploring the byte code. When you apply javap
on a class, it prints out package, protected, and public fields and methods of the classes passed. I created a class Person.scala and filled it out with the following code.
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
}
}
After compiling the code with scalac Person.scala
it generates three files with names Person.class, PersonVal.calass , PersonVar.cass
. By running javap
for each of these class files we can see how the structure would be:
>>javap Person.class
Compiled from "Person.scala"
public class Person {
public java.lang.String say();
public Person(java.lang.String, int);
}
In this case it didn't create any class varible for Person since it is declared with neither val, nor val so name and age can just be used inside constructor.
>>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);
}
In this case it has three members two for the input constructor and one for the member that we declared inside the constructore. However we don't have any setter for the input constructors so we can't change the values.
>>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);
}
It's the same as PersonVal example but we can change the values in this case with those variable_$eq
methods. it nothing just a shortened version of variable =