## 6 Functional Objects

Sample run of chapter's interpreter examples

### 6.1 A specification for class Rational

```
scala> val oneHalf = new Rational(1, 2)
oneHalf: Rational = 1/2

scala> val twoThirds = new Rational(2, 3)
twoThirds: Rational = 2/3

scala> (oneHalf / 7) + (1 - twoThirds)
res0: Rational = 17/42

```

### 6.2 Constructing a Rational

```
class Rational(n: Int, d: Int)

// In file functional-objects/ex1/Rational.scala

class Rational(n: Int, d: Int) {
println("Created "+ n +"/"+ d)
}

scala> new Rational(1, 2)
Created 1/2
res0: Rational = Rational@90110a

```

### 6.3 Reimplementing the toString method

```
// In file functional-objects/ex2/Rational.scala

class Rational(n: Int, d: Int) {
override def toString = n +"/"+ d
}

scala> val x = new Rational(1, 3)
x: Rational = 1/3

scala> val y = new Rational(5, 7)
y: Rational = 5/7

```

### 6.4 Checking preconditions

```
scala> new Rational(5, 0)
res1: Rational = 5/0

scala> new Rational(5, 0)
java.lang.IllegalArgumentException
at Rational.<init>(<console>:14)
at .<init>(<console>:6)
at .<clinit>(<console>)...

// In file functional-objects/ex4/Rational.scala

class Rational(n: Int, d: Int) {
require(d != 0)
override def toString = n +"/"+ d
}

```

```
class Rational(n: Int, d: Int) { // This won't compile
require(d != 0)
override def toString = n +"/"+ d
new Rational(n * that.d + that.n * d, d * that.d)
}

<console>:11: error: value d is not a member of Rational
new Rational(n * that.d + that.n * d, d * that.d)
^
<console>:11: error: value d is not a member of Rational
new Rational(n * that.d + that.n * d, d * that.d)
^

// In file functional-objects/ex5/Rational.scala

class Rational(n: Int, d: Int) {
require(d != 0)
val numer: Int = n
val denom: Int = d
override def toString = numer +"/"+ denom
new Rational(
numer * that.denom + that.numer * denom,
denom * that.denom
)
}

scala> val oneHalf = new Rational(1, 2)
oneHalf: Rational = 1/2

scala> val twoThirds = new Rational(2, 3)
twoThirds: Rational = 2/3

res3: Rational = 7/6

scala> val r = new Rational(1, 2)
r: Rational = 1/2

scala> r.numer
res4: Int = 1

scala> r.denom
res5: Int = 2

```

### 6.6 Self references

```
// In file functional-objects/ex6/Rational.scala

def lessThan(that: Rational) =
this.numer * that.denom < that.numer * this.denom

// In file functional-objects/ex6/Rational.scala

def max(that: Rational) =
if (this.lessThan(that)) that else this

```

### 6.7 Auxiliary constructors

```
// In file functional-objects/ex7/Rational.scala

class Rational(n: Int, d: Int) {

require(d != 0)

val numer: Int = n
val denom: Int = d

def this(n: Int) = this(n, 1) // auxiliary constructor

override def toString = numer +"/"+ denom

new Rational(
numer * that.denom + that.numer * denom,
denom * that.denom
)
}

scala> val y = new Rational(3)
y: Rational = 3/1

```

### 6.8 Private fields and methods

```
scala> new Rational(66, 42)
res6: Rational = 66/42

// In file functional-objects/ex8/Rational.scala

class Rational(n: Int, d: Int) {

require(d != 0)

private val g = gcd(n.abs, d.abs)
val numer = n / g
val denom = d / g

def this(n: Int) = this(n, 1)

new Rational(
numer * that.denom + that.numer * denom,
denom * that.denom
)

override def toString = numer +"/"+ denom

private def gcd(a: Int, b: Int): Int =
if (b == 0) a else gcd(b, a % b)
}

scala> new Rational(66, 42)
res7: Rational = 11/7

```

### 6.9 Defining operators

```
x + y

// In file functional-objects/ex9/Rational.scala

class Rational(n: Int, d: Int) {

require(d != 0)

private val g = gcd(n.abs, d.abs)
val numer = n / g
val denom = d / g

def this(n: Int) = this(n, 1)

def + (that: Rational): Rational =
new Rational(
numer * that.denom + that.numer * denom,
denom * that.denom
)

def * (that: Rational): Rational =
new Rational(numer * that.numer, denom * that.denom)

override def toString = numer +"/"+ denom

private def gcd(a: Int, b: Int): Int =
if (b == 0) a else gcd(b, a % b)
}

scala> val x = new Rational(1, 2)
x: Rational = 1/2

scala> val y = new Rational(2, 3)
y: Rational = 2/3

scala> x + y
res8: Rational = 7/6

scala> x.+(y)
res9: Rational = 7/6

scala> x + x * y
res10: Rational = 5/6

scala> (x + x) * y
res11: Rational = 2/3

scala> x + (x * y)
res12: Rational = 5/6

```

### 6.10 Identifiers in Scala

```
// In file functional-objects/ex10/Rational.scala

class Rational(n: Int, d: Int) {

require(d != 0)

private val g = gcd(n.abs, d.abs)
val numer = n / g
val denom = d / g

def this(n: Int) = this(n, 1)

def + (that: Rational): Rational =
new Rational(
numer * that.denom + that.numer * denom,
denom * that.denom
)

def + (i: Int): Rational =
new Rational(numer + i * denom, denom)

def - (that: Rational): Rational =
new Rational(
numer * that.denom - that.numer * denom,
denom * that.denom
)

def - (i: Int): Rational =
new Rational(numer - i * denom, denom)

def * (that: Rational): Rational =
new Rational(numer * that.numer, denom * that.denom)

def * (i: Int): Rational =
new Rational(numer * i, denom)

def / (that: Rational): Rational =
new Rational(numer * that.denom, denom * that.numer)

def / (i: Int): Rational =
new Rational(numer, denom * i)

override def toString = numer +"/"+ denom

private def gcd(a: Int, b: Int): Int =
if (b == 0) a else gcd(b, a % b)
}

scala> val x = new Rational(2, 3)
x: Rational = 2/3

scala> x * x
res13: Rational = 4/9

scala> x * 2
res14: Rational = 4/3

```

### 6.12 Implicit conversions

```
scala> 2 * r
<console>:7: error: overloaded method value * with
alternatives (Double)Double <and> (Float)Float <and>
(Long)Long <and> (Int)Int <and> (Char)Int <and> (Short)Int
<and> (Byte)Int cannot be applied to (Rational)
2 * r
^

scala> implicit def intToRational(x: Int) = new Rational(x)

scala> val r = new Rational(2,3)
r: Rational = 2/3

scala> 2 * r
res16: Rational = 4/3

```