次問の準備でクラスの理解も兼ねて分数クラスを作ります。
まず、クラス名はPythonと同じくFractionとします。分母・分子は都合でBigIntです。
コンストラクタ
分母と分子を引数に取ります。こんな感じでしょうか。
class Fraction(num :BigInt, den :BigInt) { val d = gcd(num, den) private val numerator = num / d private val denominator = den / d def gcd(m :BigInt, n :BigInt) :BigInt = if(n == 0) m else gcd(n, m % n) }
ただし、これではdもメンバになってしまいます。
println ((new Fraction(4, 6)).d) // 2
ちょっと無理やりっぽいですが、これでいけるようです。
class Fraction(num :BigInt, den :BigInt) { private val (numerator, denominator) = init(num, den) def init(num :BigInt, den :BigInt) = { val d = gcd(num, den).abs if(den > 0) (num / d, den / d) else (-num / d, -den / d) } def gcd(m :BigInt, n :BigInt) :BigInt = if(n == 0) m else gcd(n, m % n) }
toString
toStringをオーバーライドするとprintで表示できます。Javaと同じ?
class Fraction(num :BigInt, den :BigInt) { ... override def toString() = if(denominator != 1) numerator.toString + "/" + denominator.toString else numerator.toString ... } println (new Fraction(4, 6)) // 2/3
オーバーライドするときはoverrideと書かなければならないようです。基本クラスのメソッドをオーバーライドしているんですね。
演算子
class Fraction(num :BigInt, den :BigInt) { ... def *(f :Fraction) = new Fraction(numerator * f.numerator, denominator * f.denominator) ... } val f = new Fraction(4, 6) val g = new Fraction(1, 6) println (f * g) // 1/9
整数との演算も簡単です。
def *(n :BigInt) = new Fraction(numerator * n, denominator) ... println (f * 3) // 2
ただ、逆はできないですよね。
println (3 * f) // エラー
Fractionクラスとしてはまだまだ足りないものだらけですが、次の問題を解くためにはこれで十分です。
class Fraction(num :BigInt, den :BigInt) { private val (numerator, denominator) = init(num, den) def init(num :BigInt, den :BigInt) = { val d = gcd(num, den).abs if(den > 0) (num / d, den / d) else (-num / d, -den / d) } def *(f :Fraction) = new Fraction(numerator * f.numerator, denominator * f.denominator) def *(n :BigInt) = new Fraction(numerator * n, denominator) def +(f :Fraction) = new Fraction(numerator * f.denominator + denominator * f.numerator, denominator * f.denominator) override def toString() = if(denominator != 1) numerator.toString + "/" + denominator.toString else numerator.toString def gcd(m :BigInt, n :BigInt) :BigInt = if(n == 0) m else gcd(n, m % n) }