将密封的类声明为对象的好处

时间:2019-12-21 21:59:54

标签: kotlin sealed-class

上下文

我有这个sealed class及其每个孩子:

sealed class Section

class SearchSection : Section()
class FavoritesSection : Section()
class RecommendationsSection : Section()
class ProfileSection : Section()

但是我收到每个类声明的警告:

  

密封的子类没有状态,并且没有等价物

建议我将它们声明为:

object ProfileSection : Section()

问题

  • 这是什么目的?
  • 有什么好处?
  • 为什么我应该将它们写为object而不是class

1 个答案:

答案 0 :(得分:2)

首先让我解释一下密封类的目的是什么。 the official documentation中的第一句话说:

  

当值可以具有受限集中的一种类型但不能具有任何其他类型时,密封类用于表示受限类层次结构。 从某种意义上讲,它们是枚举类的扩展。

我确定您已经熟悉枚举,它们是这种特殊类型,可将变量定义为预定义常量之一,并且每个常量都可以存储一些其他数据。每个常数只有一个实例。至此,您可能已经注意到,这个单一实例和数据保存听起来像Kotlin对象。原来是这个枚举类:

enum class Type(val value: String) {
    A("a"),
    B("b")
}

等效于此密封类:

sealed class Type(val value: String) {
    object A : Type("a")
    object B : Type("b")
}

(实际上,枚举常量是Kotlin中的对象)。

使密封类特别之处在于,它们允许您使用类而不是对象来定义“常量”,因此它们可以具有多个实例,因此可以存储实际状态,例如:

sealed class ApiReponse

data class Success(val data: Data) : ApiResponse()
object Error : ApiResponse()

fun getResponse(): ApiResponse {
    ...
    return if (apiCall.isSuccessful) Success(apiCall.data) else Error
}

所以最后回答您的原始问题:

  

这是什么目的?

与枚举常量相同。如果您不需要在“常量”内部存储状态,而只需要一个带有可选静态数据的命名类型,则可以选择一个对象。

  

有什么好处?

     

为什么我应该将它们写为对象而不是类?

如果您不需要“常量”来具有状态,那么每次使用它时都要创建一个不同的实例,这只是浪费内存。