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。 (但是,一个缺点是它们不能很好地处理继承。)
我正在尝试重载 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。 (但是,一个缺点是它们不能很好地处理继承。)