我正在做一个需要处理“有理数”的Kotlin项目。为此,我有一个类,它将有理数存储为两个整数(分子和分母),并使用这些值执行一些算术。我遇到的问题是,其中一个要求是值被归一化。传入的值2/4应该存储为1/2,6/8应该是1/4,我还想把它变成一个“数据类”,这样我就可以利用内置的equals和hashcode函数。
我的类看起来像这样:
data class Rational(val numerator: BigInteger, val denominator: BigInteger): Comparable<Rational>
{
init {
if(denominator.equals(0))
{
throw IllegalArgumentException("0 is not a valid denominator")
}
//normalize the value by reducing to the least common denominator
val gcd = numerator.gcd(denominator)
this.numerator = numerator.div(gcd)
this.denominator = denominator.div(gcd)
}
}
infix fun BigInteger.divBy(d: BigInteger): Rational
{
return Rational(this, d)
}
fun main() {
val half = 2 divBy 4
println(half) // expected: Rational(numerator=1, denominator=2)
}
字符串
因为参数是'val',所以无法编译。我不想让属性可变,但我不确定在设置值之前如何进行计算。我不能删除修饰符,因为它们是数据类所必需的。
在设置值之前需要处理的属性的初始化过程是什么?到目前为止我能找到的唯一答案是:How to store temporary variable while initializing a Kotlin object?,它似乎是用于旧版本(1.0之前)的Kotlin。
2条答案
按热度按时间izkcnapc1#
我相信这是不可能的。根据设计,数据类是一个简单的数据保持器。如果我们向它传递一个值,我们希望它正好保存这个值。动态转换值可能被认为是一个意外的行为。也许提供一个
normalized()
成员函数或工厂函数会更好?话虽如此,我们可以通过隐藏主构造函数并为伴随对象提供
invoke()
运算符来欺骗它:字符串
当然,这并不完全是你所要求的。我们在这里没有使用构造函数,而是使用了一个看起来像构造函数的函数。另外,我们需要记住
copy()
函数,它没有进行规范化,我相信我们不能覆盖它。esbemjvw2#
为了防止以后有人遇到这种情况,我最终改为非数据类,并自己实现了equals和hashmap函数。最终结果如下所示:
字符串