CSC447

Concepts of Programming Languages

Scala Classes

Instructor: James Riely

Video

Open on youtube

Scala FP and OOP

  • Scala supports both FP and OOP

(0 to 9).toList.partition ((x:Int) => x%3 == 0)
          

class Counter:
  var n = 0
  def get () : Int = { val tmp = n; n = n + 1; tmp }

val c = new Counter()
c.get()
c.get()
          

Scala OOP

  • Brief overview of Scala OOP
  • Class definitions, fields, methods
  • Companion objects

Class Parameters

Define a class C

class C (f1:Int, val f2:Int, var f3:Int):
  //...
          
Only one constructor; has parameters f1, f2, f3

val c = new C (2, 3, 5)
            
  • Instance of C is heap allocated
  • c is a reference to instance

Class Parameters


class C (f1:Int, val f2:Int, var f3:Int):
  //...
          
f1 private and immutable; f2 immutable

scala> val c = new C (2, 3, 5)
c: C = C@8bd1b6a

scala> c.f1
<console>:10: error: value f1 is not a member of C

scala> c.f2
res1: Int = 3

scala> c.f3
res2: Int = 5

scala> c.f2 = 10
<console>:9: error: reassignment to val

scala> c.f3 = 10
c.f3: Int = 10
            

Class Parameter Details


scala> class C1(x:Int) { def double() = x+x }
defined class C1

scala> :javap -p -c -filter C1
Compiled from "<console>"
public class C1 {
  private final int x;

  public int double();
    Code:
       0: aload_0
       1: getfield      #19                 // Field x:I
       4: aload_0
       5: getfield      #19                 // Field x:I
       8: iadd
       9: ireturn

  public C1(int);
    Code:
       0: aload_0
       1: iload_1
       2: putfield      #19                 // Field x:I
       5: aload_0
       6: invokespecial #26                 // Method java/lang/Object."<init>":()V
       9: return
}
          

Class Parameter Details


scala> class C2(val x:Int) { def double() = x+x }
defined class C2

scala> :javap -p -c -filter C2
Compiled from "<console>"
public class C2 {
  private final int x;

  public int x();
    Code:
       0: aload_0
       1: getfield      #18                 // Field x:I
       4: ireturn

  public int double();
    Code:
       0: aload_0
       1: invokevirtual #23                 // Method x:()I
       4: aload_0
       5: invokevirtual #23                 // Method x:()I
       8: iadd
       9: ireturn

  public C2(int);
    Code:
       0: aload_0
       1: iload_1
       2: putfield      #18                 // Field x:I
       5: aload_0
       6: invokespecial #28                 // Method java/lang/Object."<init>":()V
       9: return
}
          

Class Parameter Details


scala> class C3(var x:Int) { def double() = x+x }
defined class C3

scala> :javap -p -c -filter C3
Compiled from "<console>"
public class C3 {
  private int x;

  public int x();
    Code:
       0: aload_0
       1: getfield      #18                 // Field x:I
       4: ireturn

  public void x_$eq(int);
    Code:
       0: aload_0
       1: iload_1
       2: putfield      #18                 // Field x:I
       5: return

  public int double();
    Code:
       0: aload_0
       1: invokevirtual #26                 // Method x:()I
       4: aload_0
       5: invokevirtual #26                 // Method x:()I
       8: iadd
       9: ireturn

  public C3(int);
    Code:
       0: aload_0
       1: iload_1
       2: putfield      #18                 // Field x:I
       5: aload_0
       6: invokespecial #30                 // Method java/lang/Object."<init>":()V
       9: return
}          

Class Body

  • Class body contains
    • val or var field declarations
    • constructor code
    • method definitions

class C (f1:Int, val f2:Int, var f3:Int):
  val f4 = f1 * f2
  var f5 = f2 * f3

  println ("Constructing instance of C")
 
  def m (x:Int) : Int =
    // cannot reassign to f1, f2, f4
    f3 = f3 + 1
    f5 = f5 + 1
    f1 * f3 * x
          

Omitting Parts

Can omit empty body

class D (f1:Int)
          
Can omit empty parentheses

class E:
  private var n:Int = 0
  def get () : Int = { val tmp = n; n = n + 1; tmp }

val o : E = new E()
o.get()
            

Companion Objects

  • Companion objects replace static components
Java

class C {
  int f1;
  int m1 () { return f1; }
  static int f2;
  static int m2 () { return f2; }
}
            
Scala

class C:
  var f1:Int = 0
  def m1 () : Int = f1

object C:
  var f2:Int = 0
  def m2 () : Int = f2
            

Companion Objects

  • Only one instance of object declarations
  • Language support for singleton design pattern

object C:
  var count:Int = 0
          

Program Startup

Java

public class C {
  public static void main (String[] args) {
    //...
  }
}
            
Scala

object C:
  def main (args:Array[String]) : Unit = 
    //...
            

Construction via Companion

  • Companion objects used to construct object
  • Companion can invoke private constructor
    • but paste together using :paste!

class Point private (private var x:Int, private var y:Int):
  def translate (xDisp:Int, yDisp:Int) : Unit = 
    x = x + xDisp
    y = y + yDisp

object Point:
  def apply (x:Int, y:Int) : Point = 
    if 0 <= x && x <= 10 && 0 <= y && y <= 10 then 
      new Point (x, y)
    else
      throw new RuntimeException ("invalid params")
          

Construction via Companion


:paste
// Entering paste mode (ctrl-D to finish)
[...snip class and object definitions here...]
// Exiting paste mode, now interpreting.

defined class Point
defined object Point

scala> Point.apply (1, 100)
java.lang.RuntimeException: invalid params

scala> Point.apply (1, 10)
res5: Point = Point@49e202ad

scala> new Point (1, 100)
<console>:10: error: constructor Point in class Point cannot be accessed in object $iw
          

Construction via Companion

apply method is the default

scala> Point (1, 100)   // means Point.apply (1, 100)
java.lang.RuntimeException: invalid params

scala> Point (1, 10)    // means Point.apply (1, 10)
res5: Point = Point@49e202ad
          

Construction via Companion

  • List class has a companion object

object List extends SeqFactory[List] with Serializable:
  def apply[A](xs: A*): List[A] = ???
  //...other methods...

List (1, 2, 3)        // means List.apply (1, 2, 3)