Programming in Scalaを読み始めた Chapter6

Rationalというクラスをつくってみる。有理数という意味あいかな

package rational

class Rational(n: Int, d: Int) {
  require(d != 0)
  private val g = gcd(n.abs, d.abs)
  val numer: Int = n/g
  val denom: Int = d/g
  def this(n: Int) = this(n, 1)
  override def toString = numer + "/" + 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.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)
  private def gcd(a: Int, b: Int): Int =
    if(b == 0) a else gcd(b, a%b)

}
scala> import rational.Rational
import rational.Rational

scala> new Rational(2,3)       
res1: rational.Rational = 2/3

scala> new Rational(2,0)
java.lang.IllegalArgumentException: requirement failed
	at scala.Predef$.require(Predef.scala:107)
	at rational.Rational.<init>(Rational.scala:4)
	at .<init>(<console>:6)
	at .<clinit>(<console>)
	at RequestResult$.<init>(<console>:3)
	at RequestResult$.<clinit>(<console>)
	at RequestResult$result(<console>)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.refle...
	
scala> val oneHalf = new Rational(1,2)
oneHalf: rational.Rational = 1/2

scala> val twoHalf = new Rational(2,3)
twoHalf: rational.Rational = 2/3

scala> oneHalf.numer
res1: Int = 1

scala> oneHalf.denom
res2: Int = 2

scala> new Rational(5)         
res0: rational.Rational = 5/1

scala> new Rational(66, 42)    
res0: rational.Rational = 11/7

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

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

scala> x * y
res0: rational.Rational = 1/3

scala> x + y
res1: rational.Rational = 7/6

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

scala> x+x*y
res3: rational.Rational = 5/6

scala> (x+x)*y
res4: rational.Rational = 2/3

scala> x+(x*y)
res5: rational.Rational = 5/6

scala> x*2
res0: rational.Rational = 4/3

scala> 2*x
<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.Rational)
       2*x
        ^

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

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

scala> 2 * r
res2: rational.Rational = 4/3