Kotlin 密封类

在本教程中,我们将着眼于Kotlin密封类。它们是什么?它们有什么用处?我们将在下面解答所有这些问题。

Kotlin 封闭类

kotlin sealed class

实施 Kotlin 密封类

Kotlin中的密封类是按照以下方式实现的。

sealed class A{
    class B : A()
    class C : A()
}

要指定一个封装类,需要添加sealed修饰符。封装类不能被实例化。因此,它们是隐式抽象类。下面的方法不可行。

fun main(args: Array<String>) 
{
    var a = A() //compiler error. Class A cannot be instantiated.
}

封装类的构造函数默认为私有。封装类的所有子类必须在同一文件中声明。封装类对编译时的类型安全非常重要,通过限制类型的集合来实现。

sealed class A{
    class B : A() 
    {
        class E : A() //this works.
    }
    class C : A()

    init {
        println("sealed class A")
    }

}

class D : A() //this works
{
class F: A() //This won't work. Since sealed class is defined in another scope.
}

使用构造函数创建一个封闭类。

sealed class A(var name: String){
    class B : A("B")
    class C : A("C")
}

class D : A("D")
fun main(args: Array<String>) {
    
    var b = A.B()
    var d = D()
}

在一个封闭类中添加数据类和对象。

fun main(args: Array<String>) {

    val e = A.E("Anupam")
    println(e) //prints E(name=Anupam)

    var d = A.D
    d.name() //prints Object D
}


sealed class A{
    class B : A()
    class C : A()
    object D : A()
    {
         fun name()
         {
             println("Object D")
         }
    }
    data class E(var name: String) : A()

}

枚举和密封类之间的区别

在 Kotlin 中,密封类可以被称为强化版的枚举类。密封类允许我们创建具有不同类型的实例,而枚举类只允许我们为所有枚举常量使用相同类型。在枚举类中是无法实现下面的情况的。

enum class Months(string: String){
January("Jan"), February(2),
}

封闭类(sealed classes)为我们提供了多个实例,从而允许所有常量仅使用一个类型。

sealed class Months {
    class January(var shortHand: String) : Months()
    class February(var number: Int) : Months()
    class March(var shortHand: String, var number: Int) : Months()
}

在你的项目中,你如何使用密封类的这个特性?在类似新闻推送的应用中,你可以按照下面所示创建三种不同的类类型,包括状态(Status)、图片(Image)和视频(Video)帖子。

sealed class Post
{
    class Status(var text: String) : Post()
    class Image(var url: String, var caption: String) : Post()
    class Video(var url: String, var timeDuration: Int, var encoding: String): Post()
}

这在枚举类中是不可能的。

密封类和当

密封类通常与when语句一起使用,因为每个子类及其类型都充当一个case。此外,我们知道密封类限制了类型。因此,when语句的else部分可以很容易地删除。下面的例子演示了相同的情况。

sealed class Shape{
    class Circle(var radius: Float): Shape()
    class Square(var length: Int): Shape()
    class Rectangle(var length: Int, var breadth: Int): Shape()
}

fun eval(e: Shape) =
        when (e) {
            is Shape.Circle -> println("Circle area is ${3.14*e.radius*e.radius}")
            is Shape.Square -> println("Square area is ${e.length*e.length}")
            is Shape.Rectangle -> println("Rectagle area is ${e.length*e.breadth}")
        }

让我们在主函数中执行如下所示的eval函数。

fun main(args: Array<String>) {

    var circle = Shape.Circle(4.5f)
    var square = Shape.Square(4)
    var rectangle = Shape.Rectangle(4,5)

    eval(circle)
    eval(square)
    eval(rectangle)
    //eval(x) //compile-time error.

}

//Following is printed on the console:
//Circle area is 63.585
//Square area is 16
//Rectangle area is 20

注意:is修饰符用于检查一个类是否为下列类型。is修饰符仅适用于类,而不适用于Kotlin对象,如下所示:

sealed class Shape{
    class Circle(var radius: Float): Shape()
    class Square(var length: Int): Shape()
    object Rectangle: Shape()
    {
        var length: Int = 0
        var breadth : Int = 0
    }
}

fun eval(e: Shape) =
        when (e) {
            is Shape.Circle -> println("Circle area is ${3.14*e.radius*e.radius}")
            is Shape.Square -> println("Square area is ${e.length*e.length}")
            Shape.Rectangle -> println("Rectangle area is ${Shape.Rectangle.length*Shape.Rectangle.breadth}")
        }

这就结束了Kotlin密封类教程。参考资料:Kotlin文档

发表回复 0

Your email address will not be published. Required fields are marked *