所以我有一个抽象类 Composition,它有两个孩子:一个是 Track,一个是 Album(这是一组 Track)。
class Composition(val name: String, ...)
class Track(name: String): Composition(name)
class Album(name: String, val tracks: List<Track>): Composition(name)
到现在为止还挺好。现在,我有添加的持续时间。它在组合中是抽象的,所以我可以在孩子中覆盖它:
abstract class Composition(...){
abstract fun getDuration(): Int
}
现在,我可以在 Track 中添加 override 方法,将其作为参数:
class Track(..., private val duration: Int): Composition(...){
override fun getDuration() = duration
}
最后,我制作了专辑,其持续时间是曲目的总和:
class Album(..., val tracks: List<Track>): Composition(...){
override fun getDuration() = tracks.sumBy { it.getDuration() }
}
它按预期工作,但我不明白为什么我不能简单地使用tracks.sumBy { it.duration }
,因为在 Kotlin 中,属性只不过是 getter 和 setter (我正在考虑getDuration
in Composition
)。
我觉得我遗漏了一些东西,因为如果相同的代码是用 Java 编写的,我将能够composition.duration
作为属性调用——所以这让我认为 Kotlin 允许它来自 Java 代码,但不允许来自 Kotlin 代码,这悲伤。
另一个例子:
假设我有一个名为 的类Artist
,他写了多个Composition
s:
class Artist(
val nom: String,
private val _compositions: MutableList<Composition> = ArrayList()
) {
// HERE (I wrote the extension method List<E>.toImmutableList)
fun getCompositions() : List<Composition> = _compositions.toImmutableList()
}
这是 Java 中的标准(通过 getter 公开集合的不可变版本,因此它们不会被修改);Kotlin 无法识别它:
val artist = Artist("Mozart")
artist.getCompositions() // Legal
artist.compositions // Illegal
我考虑过将其设为属性,但是: - 如果我选择类型List<E>
,我可以覆盖 getter 以返回不可变列表,但我不能使用常规方法(add
...),因为它List
是不可变的 - 如果我选择类型MutableList<E>
,我无法覆盖 getter 以返回ImmutableList
(这是List
我编写的子类,显然不是 的子类MutableList
)。
当有一个简单的解决方案时,我可能会做一些荒谬的事情,但现在我找不到它。
最后,我的问题是:为什么从 Kotlin 编写的手动编写的 getter 不被视为属性?
而且,如果我弄错了,解决这两种模式的预期方法是什么?