Kotlin 构造函数重载

Kotlin constructor overloading

我正在尝试重载 class 的构造函数,以便它接受字符串和整数。

class Load (val duration: Int = 0,val minrep: Int = 0,val maxrep: Int = 0): Serializable{

constructor(duration: String = "0",minrep: String = "0",maxrep: String = "0")
        : this(duration.toInt(),minrep.toInt(),maxrep.toInt())

问题是因为我被迫立即调用超级构造函数,所以我无法检查变量中的“”,这是一种可能的状态,然后将应用程序崩溃到 .toInt()。

所以我想做的是这样的:

constructor(duration: String = "0",minrep: String = "0",maxrep: String = "0") {
    if(duration == "")
        duration = "0"
            ...
    this(duration.toInt(),minrep.toInt(),maxrep.toInt())
}

但是怎么办?

我现在是这样解决的,但是来自python感觉很不性感和臃肿,一定有更好的方法:

class Load (duration: String = "0",minrep: String = "0",maxrep: String = "0"): Serializable{

var m_duration : Int = 0
var m_maxrep : Int = 0
var m_minrep : Int = 0

init{
    m_duration = if(duration=="") 0 else duration.toInt()
    m_maxrep = if(maxrep=="") 0 else maxrep.toInt()
    m_minrep = if(minrep=="") 0 else minrep.toInt()
}
constructor(duration: Int = 0,minrep: Int = 0,maxrep: Int = 0)
        : this(duration.toString(),minrep.toString(),maxrep.toString())

提取一些函数的额外数据转换逻辑并调用它而不是简单的 .toInt():

class Load(val duration: Int = 0, val minrep: Int = 0, val maxrep: Int = 0) {
    companion object {
        //`String` will have this extension function only in the scope of `Load` class
        private fun String.toIntOrZero() = toIntOrNull() ?: 0
    }
    constructor(duration: String = "0", minrep: String = "0", maxrep: String = "0")
            : this(duration.toIntOrZero(), minrep.toIntOrZero(), maxrep.toIntOrZero())
}

请注意,在此实现中,所有其他无法解析为 Int 的字符串也将退回到 0

有一种快速简便的方法;你只需要知道 Kotlin 中的 if is an expression:

class Load(val duration: Int = 0, val minrep: Int = 0, val maxrep: Int = 0): Serializable {
    constructor(duration: String = "0", minrep: String = "0", maxrep: String = "0")
        : this(if (duration == "") 0 else duration.toInt(), minrep.toInt(), maxrep.toInt())
}

但是,这很快就会变得笨拙,并且您可以通过这种方式进行的处理类型是有限的。 (正如另一个答案所示,您可以调用辅助方法,但仍然很尴尬。)

因此,更通用的解决方案是使用工厂方法:一种执行所需的任何处理,然后 然后 调用构造函数。在 Java 中,这将是一个静态方法; Kotlin 等效项是 class 的 companion object:

上的一个方法
class Load(val duration: Int = 0, val minrep: Int = 0, val maxrep: Int = 0): Serializable {
    companion object {
        operator fun invoke(duration: String = "0", minrep: String = "0", maxrep: String = "0"): Load {
            val dur = if (duration == "") 0 else duration.toInt()
            // ...
            return Load(dur, minrep.toInt(), maxrep.toInt())
        }
    }
}

这里的神奇之处在于,通过将其设为 operator fun invoke(),您可以将其称为 Load(…),因此它 看起来 就像调用普通构造函数一样!

(仅当它的作用很明显时才适用,仅从参数类型来看。 如果不明显,或者如果您需要两个具有相同参数类型的工厂方法,则常规命名方法更好。)

工厂方法使您可以更好地控制对象的创建方式:它们允许您在调用构造函数之前进行任意数量的处理;他们可以 return 一个缓存的对象,而不是每次都创建一个新的实例;如果合适的话,他们可以 return 一个 subclass。 (但是,一个缺点是它们不能很好地处理继承。)