Generics

A generic class is parameterized by a type variable. We can think of it as a function that maps types into classes.

Example: stack.scala

import scala.collection.mutable.ArrayBuffer

class Stack[T] ( val capacity: Int = 100) {
  private val elems: ArrayBuffer[T] = new ArrayBuffer[T](capacity)
  private var sp = 0
  def push(elem: T) {
    elems += elem
    sp += 1
  }
  def pop() { if (sp > 0) sp -= 1 }
  def top: Option[T] = if (sp > 0) Some(elems(sp - 1)) else None
}

Notes

·       We don't include elems and sp in the constructor's parameter list. The user doesn't get to specify these. Only the capacity can be specified and this has a default value, so its specification is optional.

·       The stack pointer (sp) is never negative.

·       The empty pair of parentheses after pop is not required, but helps distinguish parameterless procedures from parameterless functions.

·       What should we do if a user asks for the top of an empty stack? The choices: throw and exception or return an option.

A Demo

scala> val stack1 = Stack[String]
stack1: Stack[String] = Stack@680d4a6a

scala> stack1.push("one")

scala> stack1.push("two")

scala> stack1.top
res26: Option[String] = Some(two)

scala> stack1.pop

scala> stack1.top
res28: Option[String] = Some(one)

scala> stack1.pop

scala> stack1.top
res30: Option[String] = None

scala> stack1.push(10)
<console>:16: error: type mismatch;
 found   : Int(10)
 required: String
       stack1.push(10)

Notes

·       Pushing an integer onto a string stack is a type mismatch.

Constraining Type Parameters

We can constrain a type parameter to be a subtype of some other type. For example, if we only wanted our stacks to contain values, and not references, then we could write:

class Stack[T <: AnyVal] ( val capacity: Int = 100) {...}

And now:

scala> val stack = new Stack[String]
<console>:14: error: type arguments [String] do not conform to method <init>$default$1's type parameter bounds [T <: AnyVal]
Error occurred in an application involving default arguments.
       val stack = new Stack[String]