我一直在探索Kotlin,并编写了一个小程序/脚本来完成我觉得很无聊的任务。
在程序的开发中,我使用数据类来表示播放列表。在设计一个点,我想有一个特殊类型的Playlist
这是EmptyPlaylist
。
我无法使它正常工作。
您将如何与Kotlin建立这种关系?
在Java中,我只是扩展Playlist
(或者可能创建一个接口/抽象类,以便它们都可以继承)。
我只是想能够拥有一个List<Playlist>
而不是List<Playlist?>
最后,我只是创建了一个Playlist
对象,但是我对是否可以使用数据类创建IS-A层次结构感兴趣。
UPD:Kotlin Beta增加了对data
类的限制,因此答案也已更新。
- 数据类不能是抽象的,开放的,密封的或内部的;
- 数据类不能扩展其他类(但可以实现接口)。
因此,构建其层次结构的唯一选择是接口。此限制可能会在将来的版本中发布。
EmptyPlaylist
从中 继承 Playlist
是非空的想法 看起来有点矛盾,但是有一些选择:
您可以两者都实现TracksPlaylist
并EmptyPlaylist
实现一些Playlist
接口。这是合理的,因为EmptyPlaylist
可能不包含a的所有内容Playlist
。看起来像:
public interface Playlist
data class TracksPlaylist(val name: String, val tracks: List<Track>) : Playlist
data class EmptyPlaylist(val name: String): Playlist
如果您不希望EmptyPlaylist
甚至存在多个实例,则可以将其设置为val
代替不同的类,并避免进行is-checks,只需将其与
val EMPTY_PLAYLIST = TracksPlaylist("EMPTY", listOf())
当空的播放列表都相等时,这适用于单个对象足以代表所有播放列表的情况。
您可以使用sealed
类。这不允许您使用data
类,但是sealed
类可能适合于构建这样的类层次结构。
sealed
class是一个抽象类,只能在其主体内部声明其子类。这使编译器保证这些是唯一的子类。例子:
sealed class Playlist(val name: String) {
class Tracks(name: String, val tracks: List<Track>): Playlist(name)
class Playlists(name: String, val innerPlaylists: List<Playlist>): Playlist(name)
object Empty: Playlist("EMPTY")
}
之后,如果您声明了密封类的所有子类和对象,则when
无需指定else
分支就可以使用语句:
when (p) {
is Playlist.Tracks -> { /* ... */ }
is Playlist.Playlists -> { /* ... */ }
Playlist.Empty -> { /* ... */ }
}
然而,这个选项需要你来处理equals
,hashCode
,toString
,copy
和componentN
你自己,如果你需要他们。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句