如何在初始化Kotlin对象时存储临时变量?

时间:2014-11-11 07:44:32

标签: kotlin

我正在学习Kotlin,作为学习它的一部分,我想设计一个代表理性数字,要求的课程:

  • 类应包含两个不可变的整数字段:分子和分母。
  • 类应包含有效的equals,hashCode和toString实现。
  • 当初始化类时,应使用GCD删除分子和分母(这意味着Ratio(1, 2) == Ratio(2, 4 /* or 4, 8 */) or Ratio(2, 4 /* or 4, 8 */).numerator == 1, .denominator == 2等。)
  • 此类应包含mul方法,该方法采用另一个Ratio并返回当前比率和给定比率的乘法结果。

我尝试使用看起来适合该任务的数据类,但我无法定义自定义构造函数(分子和分母都需要删除到他们的GCD中)。

可能的解决方案:

class Ratio(num : Int, denom : Int) {
    val numerator = num / gcd(num, denom)
    val denominator = denom / gcd(num, denom) // GCD calculated twice!
}

定义类构造函数以便计算GCD一次的最简单方法是什么?

更新

好的,看起来我找到了可能的解决方案:

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方法

2 个答案:

答案 0 :(得分:3)

好的,我找到了答案(感谢安德烈指出在描述的用例中需要私人ctor):

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)
    }
  }
}

由于某种原因,如果在类中使用初始化程序块,'data'限定符将变得无用,因此如果您想要自定义构造逻辑并保留自动生成的hashCode / equals / toString方法,则需要使用工厂方法

答案 1 :(得分:0)

怎么样:

class Ratio(num : Int, denom : Int) {
 private val theGcd = gcd(num, denom)
 val numerator = num / theGcd
 val denominator = denom / theGcd
}
编辑:关于无用领域的公平观点。另一种方法是使用惰性评估属性。请参阅此处的文档http://kotlinlang.org/docs/reference/delegated-properties.html

这是一个(未经测试的)去看看..

import kotlin.properties.Delegates

class Ratio(num : Int, denom : Int) {
 private val theGcd: Int by Delegates.lazy {
    gcd(num, denom) 
 }

 val numerator = num / theGcd
 val denominator = denom / theGcd
}