在密封类的子类之间共享字段

问题描述 投票:0回答:1

我对 Kotlin 还比较陌生,目前正在学习密封类和接口。 我一直试图掌握的一个概念是如何使基类中的某些字段在子类之间共享(比方说,Id 字段)。现在我现在有这个:

sealed class Emprestimo(open val id: String, open val value: Double) {
  data class Credito(override val id: String, override val value: Double) : Emprestimo(id, value)
  data class Debito(override val id: String, override val value: Double) : Emprestimo(id, value)
}

这是实现扩展字段的正确方法吗?

kotlin sealed-class
1个回答
0
投票

这取决于您所说的“分享”是什么意思。

假设我们创建以下对象:

val credit1 = Emprestimo.Credito("one",   1.0)
val credit2 = Emprestimo.Credito("two",   2.0)
val debt3   = Emprestimo.Debito ("three", 3.0)
val debt4   = Emprestimo.Debito ("four",  4.0)

然后所有对象都不会与任何其他对象共享任何数据。这是非常明显的,因为必须创建对象提供这些值,并且正如您在上面看到的,它们都是不同的。从这个意义上说,不,没有任何东西与基类共享。


但也许你的意思有所不同。让我们将所有对象放入一个列表中并迭代它:

val list: List<Emprestimo> = listOf(credit1, credit2, debt3, debt4)
list.forEach {
    val id = it.id
    val value = it.value
}

虽然列表只知道基类型

Emprestimo
,但我们仍然可以访问所有对象的
id
value
属性,因为它们的 声明 与基类共享:您显式重写这些属性。从这个意义上说,
Credito
Debito
共享其属性的声明,因为它们都覆盖了Emprestimo
的属性。但请记住,每个人的
内容仍然会有所不同。


如果您确实希望子类

共享相同的内容,那么您需要另一个声明:

sealed class Emprestimo(open val id: String, open val value: Double) { val fixed = 42 data class Credito(override val id: String, override val value: Double) : Emprestimo(id, value) data class Debito(override val id: String, override val value: Double) : Emprestimo(id, value) }
新属性

fixed

现在由所有子类共享。因为它不是 
open
,所以它不能被覆盖并且永远是 
42
。但请记住,每个对象(例如credit1、credit2、debt3、debt4)都有其
自己的属性fixed
。通过声明,保证他们所有人都永远是
42
,但他们仍然拥有自己的财产。


最后,如果您希望所有实例只共享一个值,即您想要

共享相同的值,那么您需要将其移出到伴生对象

sealed class Emprestimo(open val id: String, open val value: Double) { data class Credito(override val id: String, override val value: Double) : Emprestimo(id, value) data class Debito(override val id: String, override val value: Double) : Emprestimo(id, value) companion object { const val constant = 1337 } }
伴生对象独立于类

instances,并且仅对于class存在一次,因此constant

确实只存在一次。由于它不再是子类或其实例的一部分,因此您需要在类本身上访问它:

val constant = credit1.constant // Error "Unresolved reference: constant" val constant = Emprestimo.constant
但是在子类定义的主体中,可以像它属于该类一样访问它:

data class Credito(override val id: String, override val value: Double) : Emprestimo(id, value) { fun doSomething() { val newValue = constant * 3 } }


总而言之,这不是正确或错误或最佳实践的问题,它只取决于您想要实现的目标。

© www.soinside.com 2019 - 2024. All rights reserved.