在 Kotlin 数据类的主构造函数中初始化属性

问题描述 投票:0回答:1

我正在开发一个需要处理“有理”数的 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”。我不想使属性可变,但我不确定在设置值之前如何进行计算。我无法删除修饰符,因为它们是数据类所必需的。

在设置值之前初始化需要处理的属性的过程是什么?到目前为止我能找到的唯一答案是:如何在初始化 Kotlin 对象时存储临时变量? 这似乎适用于旧版(1.0 之前)的 kotlin。

kotlin class constructor initialization
1个回答
0
投票

我相信这不是直接可能的。按照设计,数据类是一个简单的数据持有者。如果我们向它传递一个值,我们期望它准确地保存这个值。即时转换值可能被视为意外行为。也许提供一个

normalize()
成员函数或
normalized()
工厂函数会更好?

话虽如此,我们可以通过隐藏主构造函数并为伴生对象提供

invoke()
运算符来欺骗它:

fun main() {
    println(Rational(4.toBigInteger(), 8.toBigInteger())) // Rational(numerator=1, denominator=2)
}

data class Rational private constructor(val numerator: BigInteger, val denominator: BigInteger) {
    companion object {
        operator fun invoke(numerator: BigInteger, denominator: BigInteger): Rational {
            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)
            return Rational(numerator.div(gcd), denominator.div(gcd))
        }
    }
}

当然,这并不完全是您所要求的。这里我们不使用构造函数,而是使用一个看起来像构造函数的函数。另外,我们需要记住

copy()
函数不进行标准化,我相信我们不能覆盖它。

© www.soinside.com 2019 - 2024. All rights reserved.