私は Kotlin を勉強していますが、その学習の一環として、有理数を表すクラスを設計したいと考えています。
- クラスには、分子と分母の 2 つの不変整数フィールドが含まれている必要があります。
- クラスには、有効な equals、hashCode、および toString の実装が含まれている必要があります。
- クラスが初期化されるとき、分子と分母はそれらの GCD によって削除される必要があります (つまり、
Ratio(1, 2) == Ratio(2, 4 /* or 4, 8 */) or Ratio(2, 4 /* or 4, 8 */).numerator == 1, .denominator == 2
など)。 - このクラスには、別の Ratio を取り、現在の比率と指定された比率の乗算結果を返す mul メソッドを含める必要があります。
そのタスクに適していると思われるデータ クラスを使用しようとしましたが、カスタム コンストラクターを定義できないという問題がありました (分子と分母の両方を GCD から削除する必要があります)。
考えられる解決策:
class Ratio(num : Int, denom : Int) {
val numerator = num / gcd(num, denom)
val denominator = denom / gcd(num, denom) // GCD calculated twice!
}
GCD が 1 回計算されるようにクラス コンストラクターを定義する最も簡単な方法は何ですか?
アップデート
OK、可能な解決策を見つけたようです:
data class Ratio(num : Int, denom : Int) {
val numerator : Int
val denominator : Int
{
val gcd = calcGcd(num, denom)
numerator = num / gcd
denominator = denom / gcd
}
}
しかし、それはそのデータ修飾子を役に立たなくします - この変更の後、Ratio クラスは自動生成された equals/hashCode/toString を持たなくなりました。
最新バージョンの Kotlin - 0.9.66 で検証済み
その動作を再現するプログラム:
data class Ratio(num : Int, denom : Int) {
val numerator : Int
val denominator : Int
{
val gcd = BigInteger.valueOf(num.toLong()).gcd(BigInteger.valueOf(denom.toLong())).intValue();
numerator = num / gcd;
denominator = denom / gcd
}
}
data class Ratio2(val num : Int, val denom : Int)
fun main(args: Array<String>) {
println("r = " + Ratio(1, 6).toString())
println("r2 = " + Ratio2(1, 6).toString())
}
出力:
r = Ratio@4ac68d3e
r2 = Ratio2(num=1, denom=6)
Ratio が toString メソッドを自動生成しなくなったことは明らかです