我有一个带有命名参数的Kotlin类,未指定参数的默认值。我正在尝试找出如何为一个参数创建自定义设置器的方法,尽管似乎很简单,但似乎无法弄清楚我在做什么错。这是该类的简化版本:
class ItemObject(var itemNumber: String = "",
var itemQty: Int = 0)
我可以使用此类的属性,而不会出现itemObject.itemQty = itemObject.itemQty + 1(同时访问getter和setter)。
但是,我想创建一个自定义设置器,以防止itemQty降至零以下。因此,我尝试了以下主题的多种变体:
class ItemObject(var itemNumber: String = "",
itemQty: Int = 0) {
var itemQty: Int = 0
set(value: Int) =
if (value >= 0) {
itemQty = value // Don't want to go negative
} else {
}
}
该编译没有问题,但是似乎将默认的itemQty保持为零(或类似的东西-我没有找到它)。
有人能指出我正确的方向吗?我当然会很感激-这是我的第一个Kotlin项目,可能需要一些帮助。 :)
答案 0 :(得分:3)
vetoable
的用途是
var quantity: Int by Delegates.vetoable(0) { _, _, new ->
new >= 0
}
返回true
接受该值,返回false
拒绝该值。
答案 1 :(得分:1)
好吧,您将实数字段初始化为0并忽略了传递的值...而是使用传递的构造函数参数初始化属性:
class Item(_itemQty: Int = 0) {
var itemQty: Int = Math.max(0, _itemQty)
set(v) { field = Math.max(0, v) }
}
(我使用了两个不同的标识符来分隔参数和属性,如注释中所述,您也可以为属性和参数使用相同的名称[但请注意,这可能会增加混乱))。
您还应该设置backing field,而不是设置器本身,否则设置器将无休止地递归。
如果设置器非常复杂,并且还需要将其应用于初始值,则可以初始化属性,然后使用参数执行设置器:
class Item(_itemQty: Int = 0) {
var itemQty: Int = 0
set(v) { field = Math.max(0, v) }
init { itemQty = _itemQty }
}
作为基于意见的附带说明,item.itemQty
并不是真正的描述性内容,item.quantity
更具可读性。
答案 2 :(得分:0)
有多种防止值低于零的方法。
一种是无符号类型。目前处于实验阶段。 UInt
就您而言
class ItemObject(var itemNumber: String = "",
var itemQty: UInt = 0u
)
如果您不关心值溢出-可以选择
另一种方法是财产委托
class ItemObject(var itemNumber: String = "", itemQty: Int = 0) {
var itemQty: Int by PositiveDelegate(itemQty)
}
class PositiveDelegate(private var prop: Int) {
operator fun getValue(thisRef: Any?, property: KProperty<*>): Int = prop
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) {
if (value >= 0) prop = value
}
}
第三种带有自定义设置器的方法在其他答案中有所描述。