I am reading the Scala in Examples book and almost every example there has the following construction:
abstract class Stack[A] {
def push(x: A): Stack[A] = new NonEmptyStack[A](x, this)
def isEmpty: Boolean
def top: A
def pop: Stack[A]
}
class EmptyStack[A] extends Stack[A] {
def isEmpty = true
def top = error("EmptyStack.top")
def pop = error("EmptyStack.pop")
}
class NonEmptyStack[A](elem: A, rest: Stack[A]) extends Stack[A] {
def isEmpty = false
def top = elem
def pop = rest
}
And I have the following two interconnected questions:
1) Is it a common Scala practice to represent empty and non-empty elements as separate classes? If yes then why?
2) Why do the children both implement the same dumb ethod ‘isEmpty’ when it is possible and, to me, more sensible to do this in the parent class?
I would like to know the deepest of the philosophy involved here.
1) Yes it is common to have separate classes for empty and non-empty containers, this is generally called an algebraic data structure, however it is usually not so apparent. For example, Scala’s List has two classes,
Nilto represent an empty list, and::that contains one element and another list. Sowhile usually referred to by the
List[T]trait, is really an instance of:: [B] (hd: B, tl: List[B])that looks like:2) Each class must implement the
isEmptymethod becuase if you notice, the value is different in each child class. It simply saves some computation to figure out whether an instance ofStackis empty or not, since each child type already knows this at compile-time.