我正在Kotlin实施可以接收来自某些用户的越界输入的变量。我希望能够选择性地调用(仅限来自这些不受信任的用户的输入)可以返回null的验证构造函数,然后使用Elvis运算符指定无效输入的默认值,如:{{1} }。我目前正在使用伴随对象方法来验证输入:
var myFoo = Foo.fromInt(i) ?: 1
当我继承open class Foo(val x:Int) { // relies on valid x in 1..3
companion object {
fun fromInt(x: Int): Foo? = if (x in 1..3) Foo(x) else null
}
}
class Bar(x:Int) : Foo(x)
fun main(args:Array<String>) {
println(Foo.fromInt(2)) // Foo(2)
println(Foo.fromInt(20)) // null
// println(Bar.fromInt(2))
// would like Bar(2) but as expected, companion isn't inherited
}
时,我知道我必须重新创建伴随对象。我试过从抽象类继承伴侣;但是,对Foo
的调用仍然指向Foo(x)
而不是Foo
,除非我在每个子类的同伴中覆盖Bar
。是否有更好或更多的Kotlin-idomatic方法来处理这种可以返回fromInt
而不是创建请求对象的验证构造函数模式?
答案 0 :(得分:4)
你可以简单地使用一个构造函数并始终验证其参数x
并将其分配给这样的属性:
open class Foo (x: Int) { // relies on valid x in 1..3
val x: Int = if (x in 1..3) x else 1
}
class Bar(x: Int) : Foo(x)
现在使用不在范围内的值调用构造函数,创建了一个默认的Foo
,这基本上就是我想要的。在我看来,如果你抛出IllegalArgumentException
而不是在幕后创建默认值会更好。你觉得怎么样?
答案 1 :(得分:3)
您可以使用init块以及require
。
open class Foo(val x:Int) {
init {
require(x in 1..3) {
"relies on valid x in 1..3"
}
}
}
class Bar(x:Int) : Foo(x)
示例运行:
>>> open class Foo(val x:Int) {
... init {
... require(x in 1..3) {
... "relies on valid x in 1..3"
... }
... }
... }
>>> class Bar(x:Int) : Foo(x)
>>> val b = Bar(3)
>>> val b = Bar(4)
java.lang.IllegalArgumentException: relies on valid x in 1..3
at Line_18$Foo.<init>(Line_18.kts:3)
at Line_19$Bar.<init>(Line_19.kts:1)
>>> b.x
res22: kotlin.Int = 3
答案 2 :(得分:1)
您还可以查找“重载invoke()函数以进行构造函数验证” 。
h1
}
class Student private constructor(val rollNo: Int) {
companion object {
operator fun invoke(rollNo: Int): Student {
//Do your validation here
if (rollNo < 1) {
throw Exception() // or any default Student
} else
return Student(rollNo)
}
}
这种方法隐藏了构造函数(私有),并且由于语法过载,看起来我们正在构造函数调用。