Jump to content

Scala/Classes

From Wikibooks, open books for an open world

In Scala, a class is a type with members such as fields and methods. Class instances can be parameterized with values, and classes can be parameterized with types, which is covered under Scala/Type_parameters.

Classes

[edit | edit source]

A simple example of a class:

class SimpleClass
val simple1 = new SimpleClass
val simple2 = new SimpleClass

In the first line, the keyword "class" is used to start the definition of the class. "class" is followed by the name of the class, "SimpleClass". This defines a class with the name of "SimpleClass". In the second line, a value named "simple1" is assigned the result of the expression "new SimpleClass". The "new" keyword creates an instance given a class name and returns a reference to that instance, and "new SimpleClass" creates a new instance of type "SimpleClass". In the third line, a value named "simple2" is assigned the result of the expression "new SimpleClass", creating another new instance of type "SimpleClass". Thus, the values named "simple1" and "simple2" each hold a reference to a different instance of type "SimpleClass".

Members

[edit | edit source]

A class can contain members such as fields:

class FieldsClass {
  val name = "SomeName"
  var num = 0
}

In the first line, a class named "FieldsClass" is declared. After the name "FieldsClass" comes "{", which begins the body of the class definition. The second line declares a field, in this case a value named "name" assigned the string "SomeName". The third line also declares a field, in this case a variable named "num", assigned the number '0'. The fourth line contains a closing "}", which ends the body of the class definition.

The members of a class can be accessed by using ".":

val fields1 = new FieldsClass
val fields2 = new FieldsClass
fields1.num = 3
fields2.num = 16
println("fields1.num is: " + fields1.num) //Prints "fields1.num is: 3".
println("fields2.num is: " + fields2.num) //Prints "fields2.num is: 16".

The first and second line declares two values named "fields1" and "fields2", each containing a reference to an instance of "FieldsClass". The third line starts with "fields1.num". "." is used to access a member of an instance. The expression before "." specifies the instance, and the name after specifies the member. In this case, the instance specified is the instance referenced in "fields1", and the member specified is the field "num". Following "fields1.num" is an assignment with the number 3, assigning the number 3 to the "num" field in the first "FieldsClass" instance. The fourth line is like the third, except the number 16 is assigned to the "num" field in the second "FieldsClass" instance. The fifth and sixth lines accesses the two instances and prints their values of the field "num", which is 3 for the first instance and 16 for the second instance.

Classes can also have functions as members. These functions are called methods:

class Counter {
  var count = 0
  def incrementAndGet = {count += 1; count}
}
val counter1 = new Counter
println("Count is: " + counter1.count) //Prints "Count is: 0".
println("Count is: " + counter1.incrementAndGet) //Prints "Count is: 1".
println("Count is: " + counter1.count) //Prints "Count is: 1".

In the first four lines, a class named "Counter" is defined. The third line defines a method just like a function is defined. In the fifth line, a new "Counter" instance is created and assigned to the value named "counter1".

In the sixth line, the count of the instance is printed, which is 0. In the seventh line, the "incrementAndGet" method of "Counter" is accessed using "." like other members and is called. Note the method assigns count to incrementAndGet after incrementing count by 1, so the count of the instance is printed which is 1. In the eighth line, the count of the instance is again printed, giving the incremented value of 1.

Constructors

[edit | edit source]

Class instances can be parameterized with values through constructors. A simple example:

class Circle(r:Double) {
  def area = math.Pi * math.pow(r, 2)
}
val circle1 = new Circle(10.0)
val circle2 = new Circle(20.0)
println("Circle 1's area: " + math.round(circle1.area)) //Prints "Circle 1's area: 314".
println("Circle 2's area: " + math.round(circle2.area)) //Prints "Circle 2's area: 1257".

The first line starts declaring a new class with the name "Circle". After the name comes "(r:Double)", which defines the main constructor of the class. The main constructor consists of a pair of parenthesis containing a comma-separated list of parameters with types. In this case, a single parameter named "r" with the type "Double" is defined. The second line defines a method for calculating the area of the circle, which uses the parameter "r" defined in the main constructor, and the third line ends the class definition. The fourth line defines a new value named "circle1", and assigns it the result of the expression "new Circle(10.0)". The pair of parenthesis contains the arguments to the main constructor of "Circle", which in this case is "10.0". Thus, "circle1" contains a reference to an instance of "Circle" which is parameterized with "r" equal "10.0". The same goes for the fifth line, except the instance of "circle2" has "r" equal "20.0". In the sixth and seventh line, the areas of the circles are printed.

When declaring the list of parameters in a class, there are three options for qualifiers: None, "val" and "var. If there is no qualifier, as seen before, the parameter can only be accessed inside the class. If the qualifier is "val", the parameter can be accessed outside the class, but not assigned to. If the qualifier is "var", the parameter can be accessed outside the class, and can be assigned to.

Example of using "val" in the parameter list:

class Point(val x:Int, val y:Int, val z:Int)
val p1 = new Point(3, 10, -5)
println("p1's coordinates are: " + p1.x + ", " + p1.y + ", " + p1.z) //Prints "p1's coordinates are: 3, 10, -5".

In the first line, the parameters are all qualified with "val". In the second line, a "Point" instance is constructed, and in the third line, the parameters of the "Point" instance are accessed outside the definition of "Point".

Example of using "var" in the parameter list:

class Accumulator(var sum:Int)
val accumulator1 = new Accumulator(30)
println("Sum is: " + accumulator1.sum) //Prints "Sum is: 30".
accumulator1.sum += 50
println("Sum is: " + accumulator1.sum) //Prints "Sum is: 80".

Auxiliary constructors

[edit | edit source]

Auxiliary constructors are the alternative constructors for a class and are defined as methods in the class with name "this". A class can have many auxiliary constructors but they should have different signatures and must call the previously defined constructors.

class Car(val color:String,val year:Int)
{
  def this(){
    this("Black",2010)   //Auxiliary constructor with defaults
  }

  def this(color:String) {
    this(color,2010)
  }

  def this(year:Int){
    this("Black",year)
  }
}

object Car {
   def main(args:Array[String])= {
    //You can instantiate the Car with different constructor signatures
    val blackCar = new Car()
    val redCar = new Car("Red")
    val defCar = new Car("Green", 2013)
    val oldCar = new Car(1990)
  }
}

In the above example we have three auxiliary constructors.

Apply

[edit | edit source]