美文网首页Kotlin从入门到放弃Kotlin学习日记
【Kotlin学习日记】Day14:密封类

【Kotlin学习日记】Day14:密封类

作者: William李梓峰 | 来源:发表于2017-07-04 17:54 被阅读53次

    大家好,我是William李梓峰,欢迎加入我的Kotlin学习之旅。
    今天是我学习 Kotlin 的第十四天,内容是 Sealed Classes - 密封类。

    官方文档:

    Sealed Classes - 密封类

    Sealed classes are used for representing restricted class hierarchies, when a value can have one of the types from a limited set, but cannot have any other type.
    密封类是用于表示等级严谨的类,当一个值可以从一个有限集中拥有一个类型而不能有其他类型,密封类就能发挥其作用。(写的有点飘,靠谱的理解在下面~)

    They are, in a sense, an extension of enum classes: the set of values for an enum type is also restricted, but each enum constant exists only as a single instance, whereas a subclass of a sealed class can have multiple instances which can contain state.
    密封类,实际上是一个枚举类的扩展形式:集合的枚举类型是严格要求的,但是每个枚举常量仅存在一个单例,而密封类的子类可以包含状态。

    To declare a sealed class, you put the sealed modifier before the name of the class. A sealed class can have subclasses, but all of them must be declared in the same file as the sealed class itself. (Before Kotlin 1.1, the rules were even more strict: classes had to be nested inside the declaration of the sealed class).
    为了声明一个密封类,你可以在类的前面写 sealed 修饰符。一个密封父类可以拥有密封子类,但是所有密封子类都必须声明在同一个文件里面,该文件就是密封父类声明所在的地方。(在 Kotlin 1.1 之前,这个规则更加苛刻:子类必须在父类内部声明,多恶心)

    sealed class Expr
    data class Const(val number: Double) : Expr()
    data class Sum(val e1: Expr, val e2: Expr) : Expr()
    object NotANumber : Expr()
    

    (The example above uses one additional new feature of Kotlin 1.1: the possibility for data classes to extend other classes, including sealed classes.)
    (上面的例子使用了 Kotlin 1.1的一个新特性:数据类可以继承其他类,包括密封类)

    Note that classes which extend subclasses of a sealed class (indirect inheritors) can be placed anywhere, not necessarily in the same file.
    要知道的是,那些继承了密封类的子类(间接继承)可以放在任何地方,不一定是在同一个文件内部。(例如数据类继承了某个密封类,而这个数据类可以放置任何一个地方,不一定要在密封类所在的文件下)

    The key benefit of using sealed classes comes into play when you use them in a when expression. If it's possible to verify that the statement covers all cases, you don't need to add an else clause to the statement.
    使用密封类最关键的好处就是在 when 表达式 那里的应用。如果判断语句覆盖了所有的密封类实例,则你不再需要额外写 else 语句。(好像方便了一点,不过说真的,密封类相当于枚举类,唯一不同就是普通类可以继承密封类,而枚举类则不行。)

    fun eval(expr: Expr): Double = when(expr) {
        is Const -> expr.number
        is Sum -> eval(expr.e1) + eval(expr.e2)
        NotANumber -> Double.NaN
        // the `else` clause is not required because we've covered all the cases
    }
    

    这里官方文档没有给出丰富的密封类的使用例子,可能好戏在后头,例如 Kotlin Koan。

    相关文章

      网友评论

      • 0416119a816f:必须放在同意文件下的子类是指sealed修饰的子类嘛,普通类可以随便放?
        0416119a816f: @艾尔欧唯伊 不是数据类呢。。不是还有几种类么。。
        William李梓峰:@艾尔欧唯伊 是的,后面就讲到了 data class 继承了 sealed class,data class可以随便放

      本文标题:【Kotlin学习日记】Day14:密封类

      本文链接:https://www.haomeiwen.com/subject/morxhxtx.html