Kotlin Corda状态演化-可空与默认属性

Kotlin Corda状态演化-可空与默认属性,kotlin,corda,Kotlin,Corda,在Corda中,向状态添加新属性(状态演化)要求新属性可以为空,以便与状态的以前版本保持向后兼容 data class Version1DummyState( override val participants: List<AbstractParty> ) : ContractState data class Version2DummyState( override val participants: List<AbstractParty>, v

在Corda中,向状态添加新属性(状态演化)要求新属性可以为空,以便与状态的以前版本保持向后兼容

data class Version1DummyState(
    override val participants: List<AbstractParty>
) : ContractState

data class Version2DummyState(
    override val participants: List<AbstractParty>,
    val myNewProperty: String? = null
) : ContractState
数据类版本1dummystate(
覆盖val参与者:列表
):合同状态
数据类Version2DummyState(
覆盖val参与者:列表,
val myNewProperty:字符串?=null
):合同状态
由于Kotlin还支持具有默认值的属性,我想知道为什么状态演化仅限于可为null的类型的属性,而不限于不可为null的属性,前提是这些属性具有默认值

data class Version2DumyState(
    override val participants: List<AbstractParty>,
    val myNewProperty: String = "Hello, world."
) : ContractState
数据类版本2dumyState(
覆盖val参与者:列表,
val myNewProperty:String=“你好,世界。”
):合同状态

我提出这一问题的理由来自于查看隐式升级示例,在该示例中,债务国被升级为允许债务人违约
true
false
准确地表示债务人是否违约,但
null
没有。使用默认值
false
升级的能力似乎比使用可空字段更自然。

我认为可以通过使用
@JVMLowloads
标记构造函数来实现这一点:

data class DummyState @JvmOverloads constructor(
    override val participants: List<AbstractParty>,
    val myNewProperty: String = "blah"
) : ContractState
数据类DummyState@JvmOverloads构造函数(
覆盖val参与者:列表,
val myNewProperty:String=“blah”
):合同状态

(不要将版本号放入状态类名称中)

@JvmOverloads
使反序列化引擎可以看到“旧”构造函数进行匹配

但是,在这里最好使用一行代码来明确说明,如:

val inDefault:Boolean get()=myNewProperty?:false

fun priceOr(默认值:金额=0.USD)get()=price?:默认值

如果你真的想要这个

向后兼容性和默认值需要非常小心地处理。一个常见的错误是对新引入的字段使用默认值零/空字符串/false,即使这些值对应用程序具有语义意义。也就是说,知道旧消息没有指定某些内容是有价值的信息,不应该丢失或替换为脆弱的哨兵值。考虑新的领域“价格”。价格不能为负,所以开发者可能会将默认值设置为零。但是,为免费的东西定价是一件有意义的事情——也许不是在今天的商业场景中,但也许是在明天?现在你有问题了


Kotlin的类型系统和语法非常擅长处理缺少的值。使用
?:
操作员很容易在使用站点替换默认值,我担心建立一种惯例,即始终在施工站点提供默认值,以便初级开发人员在不知道潜在后果的情况下遵循。显式地公开默认值可能被替换的事实迫使人们考虑这是否真的合乎逻辑。

(不要将版本号放入状态类名称中)-我们应该按包名进行版本设置,对吗?我认为使用一组定义良好的常量对象,如果在对象初始化时没有已知的实际值,则强制其中一个作为默认值比null更安全。例如,一组三个对象:[NEEDS\u UPDATE,NEEDS\u UPDATE\u RAISE\u ON\u GET,DOES\u NOT\u APPLY]将允许创建更安全的getter,以便在请求状态演化后的非初始化值时,可以明智地决定何时中止或继续。