5

私は 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 メソッドを自動生成しなくなったことは明らかです

4

2 に答える 2

3

OK、私は答えを見つけました(説明されたユースケースでプライベートctorを持つ必要性を指摘したAndreyに感謝します):

data class Ratio private (val numerator : Int, val denominator : Int) {
  class object {
    fun create(numerator : Int, denominator : Int) : Ratio {
      val gcd = BigInteger.valueOf(numerator.toLong()).gcd(BigInteger.valueOf(denominator.toLong())).intValue();
      return Ratio(numerator / gcd, denominator / gcd)
    }
  }
}

クラスで初期化ブロックが使用されている場合、何らかの理由で「データ」修飾子が役に立たなくなるため、カスタム構築ロジックを持ち、自動生成された hashCode/equals/toString メソッドを保持したい場合は、ファクトリ メソッドを使用する必要があります。

于 2014-11-11T09:26:41.600 に答える