layout | title | partof | num | next-page | previous-page | topics | prerequisite-knowledge | redirect_from |
---|---|---|---|---|---|---|---|---|
tour | Classes | scala-tour | 4 | default-parameter-values | unified-types | classes | no-return-keyword, type-declaration-syntax, string-interpolation, procedures | /tutorials/tour/classes.html |
Classes in Scala are blueprints for creating objects. They can contain methods, values, variables, types, objects, traits, and classes which are collectively called members. Types, objects, and traits will be covered later in the tour.
A minimal class definition is simply the keyword class
and an identifier. Class names should be capitalized.
{% tabs class-minimal-user class=tabs-scala-version %}
{% tab 'Scala 2' for=class-minimal-user %}
classUservaluser1=newUser
The keyword new
is used to create an instance of the class. {% endtab %}
{% tab 'Scala 3' for=class-minimal-user %}
classUservaluser1=User()
We call the class like a function, as User()
, to create an instance of the class. It is also possible to explicitly use the new
keyword, as new User()
, although that is usually left out. {% endtab %}
{% endtabs %}
User
has a default constructor which takes no arguments because no constructor was defined. However, you'll often want a constructor and class body. Here is an example class definition for a point:
{% tabs class-point-example class=tabs-scala-version %}
{% tab 'Scala 2' for=class-point-example %}
classPoint(varx:Int, vary:Int) { defmove(dx: Int, dy: Int):Unit= { x = x + dx y = y + dy } overridedeftoString:String=s"($x, $y)" } valpoint1=newPoint(2, 3) println(point1.x) // prints 2 println(point1) // prints (2, 3)
{% endtab %}
{% tab 'Scala 3' for=class-point-example %}
classPoint(varx:Int, vary:Int):defmove(dx: Int, dy: Int):Unit= x = x + dx y = y + dy overridedeftoString:String=s"($x, $y)"endPointvalpoint1=Point(2, 3) println(point1.x) // prints 2 println(point1) // prints (2, 3)
{% endtab %}
{% endtabs %}
This Point
class has four members: the variables x
and y
and the methods move
and toString
. Unlike many other languages, the primary constructor is in the class signature (var x: Int, var y: Int)
. The move
method takes two integer arguments and returns the Unit value ()
, which carries no information. This corresponds roughly to void
in Java-like languages. toString
, on the other hand, does not take any arguments but returns a String
value. Since toString
overrides toString
from AnyRef
, it is tagged with the override
keyword.
Constructors can have optional parameters by providing a default value like so:
{% tabs class-point-with-default-values class=tabs-scala-version %}
{% tab 'Scala 2' for=class-point-with-default-values %}
classPoint(varx:Int=0, vary:Int=0) valorigin=newPoint// x and y are both set to 0valpoint1=newPoint(1) // x is set to 1 and y is set to 0 println(point1) // prints (1, 0)
{% endtab %}
{% tab 'Scala 3' for=class-point-with-default-values %}
classPoint(varx:Int=0, vary:Int=0) valorigin=Point() // x and y are both set to 0valpoint1=Point(1) // x is set to 1 and y is set to 0 println(point1) // prints (1, 0)
{% endtab %}
{% endtabs %}
In this version of the Point
class, x
and y
have the default value 0
so no arguments are required. However, because the constructor reads arguments left to right, if you just wanted to pass in a y
value, you would need to name the parameter.
{% tabs class-point-named-argument class=tabs-scala-version %}
{% tab 'Scala 2' for=class-point-named-argument %}
classPoint(varx:Int=0, vary:Int=0) valpoint2=newPoint(y =2) println(point2) // prints (0, 2)
{% endtab %}
{% tab 'Scala 3' for=class-point-named-argument %}
classPoint(varx:Int=0, vary:Int=0) valpoint2=Point(y =2) println(point2) // prints (0, 2)
{% endtab %}
{% endtabs %}
This is also a good practice to enhance clarity.
Members are public by default. Use the private
access modifier to hide them from outside of the class.
{% tabs class-point-private-getter-setter class=tabs-scala-version %}
{% tab 'Scala 2' for=class-point-private-getter-setter %}
classPoint { privatevar_x=0privatevar_y=0privatevalbound=100defx:Int= _x defx_=(newValue: Int):Unit= { if (newValue < bound) _x = newValue else printWarning() } defy:Int= _y defy_=(newValue: Int):Unit= { if (newValue < bound) _y = newValue else printWarning() } privatedefprintWarning():Unit= println("WARNING: Out of bounds") } valpoint1=newPoint point1.x =99 point1.y =101// prints the warning
{% endtab %}
{% tab 'Scala 3' for=class-point-private-getter-setter %}
classPoint:privatevar_x=0privatevar_y=0privatevalbound=100defx:Int= _x defx_=(newValue: Int):Unit=if newValue < bound then _x = newValue else printWarning() defy:Int= _y defy_=(newValue: Int):Unit=if newValue < bound then _y = newValue else printWarning() privatedefprintWarning():Unit= println("WARNING: Out of bounds") endPointvalpoint1=Point() point1.x =99 point1.y =101// prints the warning
{% endtab %}
{% endtabs %}
In this version of the Point
class, the data is stored in private variables _x
and _y
. There are methods def x
and def y
for accessing the private data. def x_=
and def y_=
are for validating and setting the value of _x
and _y
. Notice the special syntax for the setters: the method has _=
appended to the identifier of the getter and the parameters come after.
Primary constructor parameters with val
and var
are public. However, because val
s are immutable, you can't write the following.
{% tabs class-point-cannot-set-val class=tabs-scala-version %}
{% tab 'Scala 2' for=class-point-cannot-set-val %}
classPoint(valx:Int, valy:Int) valpoint=newPoint(1, 2) point.x =3// <-- does not compile
{% endtab %}
{% tab 'Scala 3' for=class-point-cannot-set-val %}
classPoint(valx:Int, valy:Int) valpoint=Point(1, 2) point.x =3// <-- does not compile
{% endtab %}
{% endtabs %}
Parameters without val
or var
are private values, visible only within the class.
{% tabs class-point-non-val-ctor-param class=tabs-scala-version %}
{% tab 'Scala 2' for=class-point-non-val-ctor-param %}
classPoint(x: Int, y: Int) valpoint=newPoint(1, 2) point.x // <-- does not compile
{% endtab %}
{% tab 'Scala 3' for=class-point-non-val-ctor-param %}
classPoint(x: Int, y: Int) valpoint=Point(1, 2) point.x // <-- does not compile
{% endtab %}
{% endtabs %}
- Learn more about Classes in the Scala Book
- How to use Auxiliary Class Constructors