【发布时间】:2018-11-12 02:28:24
【问题描述】:
所以我有一个抽象类 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)
到目前为止,一切都很好。现在,我有添加的持续时间。它在 Composition 中是抽象的,所以我可以在子项中覆盖它:
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(我正在考虑 Composition 中的 getDuration)。
我觉得我遗漏了一些东西,因为如果相同的代码是用 Java 编写的,我可以将 composition.duration 作为属性调用——这让我认为 Kotlin 允许从 Java 代码中调用它,但是不是来自 Kotlin 代码,这很可悲。
另一个例子:
假设我有一个名为Artist的班级,他写了多个Compositions:
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 视为属性?
如果我弄错了,解决这两种模式的预期方法是什么?
【问题讨论】:
标签: kotlin