Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Object orientation in Scala

Tags:

scala

From Martin Odersky's Scala course I have the following Exercise (this a video exercise in which answer is given):

" Provide an implementation of the abstract class Nat that represents non-negative integers

Do not use standard numerical classes in this implementation. Rather, implement a sub-object and a sub-class.

One for the number zero, the other for strictly prositive numbers. "

Here is the code :

abstract class Nat {
  def isZero : scala.Boolean
  def predecessor : Nat
  def successor = new Succ(this)
  def + (that : Nat) : Nat
  def - (that : Nat) : Nat
}

object Zero extends Nat {
  def isZero = true
  def predecessor = throw new Error("0.predecessor")
  def + (that: Nat) = that
  def - (that: Nat) = if(that.isZero) this else throw new Error("negative number")
}

class Succ(n : Nat) extends Nat {
  def isZero = false
  def predecessor = n
  def +(that : Nat) = new Succ(n + that)
  def -(that: Nat) = n - that.predecessor
}

Within a Scala worksheet I have :

object NatTests {
  new Successor(Zero).+(new Successor(Zero))  
}

Which returns a new Sucessor. I don't think I'm understanding this code fully as I should be able to add non zero objects without extending the code ? If so, how is this accomplished ?

like image 771
blue-sky Avatar asked Apr 25 '13 15:04

blue-sky


1 Answers

You are able to add non zero numbers / objects without extending any of the classes Nat, Zero, or Succ. When you use an object natObj of type Nat and construct a new object new Succ(natObject) that new object represents a number that is one higher than the number that natObj represents.

Maybe being able to view the objects, makes this a bit clearer:

abstract class Nat {
  def isZero : Boolean
  def predecessor : Nat
  def successor = new Succ(this)
  def + (that : Nat) : Nat
  def - (that : Nat) : Nat
}

object Zero extends Nat {
  def isZero = true
  def predecessor = throw new Error("0.predecessor")
  def + (that: Nat) = that
  def - (that: Nat) = if(that.isZero) this else throw new Error("negative number")

  override def toString = "0 => Zero"
}

class Succ(n : Nat) extends Nat {
  def isZero = false
  def predecessor = n
  def + (that : Nat) = new Succ(n + that)
  def - (that: Nat) = if (that.isZero) this else n - that.predecessor

  override def toString = {
    def findNumber(nat: Nat): Int = 
      if (nat.isZero) 0 
      else 1 + findNumber(nat.predecessor)
    val number = findNumber(this)
    String.valueOf(number) + " => " + 
            ((1 to number) fold ("Zero")) ( (s,_) => "Succ(" + s + ")")
  }
}

Now your Scala worksheet will show you the number an object represents and its internal structure:

object NatTests extends App {
  val nat0 = Zero                                 
  val nat1 = new Succ(Zero)                       
  val nat2 = new Succ(nat1) // or new Succ(new Succ(Zero))
  val nat3 = new Succ(nat2) // or new Succ(new Succ(new Succ(Zero)))

  println(nat0)             //> 0 => Zero
  println(nat1)             //> 1 => Succ(Zero)
  println(nat2)             //> 2 => Succ(Succ(Zero))
  println(nat3)             //> 3 => Succ(Succ(Succ(Zero)))
  println(nat2 + nat2)      //> 4 => Succ(Succ(Succ(Succ(Zero))))
  println(nat3 + nat2)      //> 5 => Succ(Succ(Succ(Succ(Succ(Zero)))))
}
like image 89
Tilo Avatar answered Oct 12 '22 22:10

Tilo