Kotlin中的数据类(data class)和密封类(sealed class)和枚举类(enum class)

数据类

1.什么是data class

data class 就是一个类中包含一些数据字段。

2.Kotlin中 data class 设计的好处

在Java中我们常用的bean类,每一个变量我们都需要写getter,setter方法,有时候还要重写toString,equals等方法,尽管工具会帮我们一键生成,但是代码量要写很多,显得有点臃肿,不灵活。

例如:同样实现一个bean类,Java的实现方式是

public class JavaBean {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "JavaBean{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

而在Kotlin中:一行代码搞定~~

data class KotlinBean(val name:String,val age:Int)

这是由于在Kotlin中我们不需要手动去敲这些代码了,编译器在背后默默给我们生成了这些东西

  • setter/getter
  • toString()
  • equals()
  • hashCode()
  • componentN()
  • copy()

前三个方法是Kotlin中超级父类Any类中定义的。

copy()方法:就是创建一个当前对象的一份拷贝,并且在copy的过程中可以选择性改变拷贝对象的属性值,而原来对象的属性值不会改变。浅拷贝

componentN()方法:能够保证数据类可以使用解构声明,有了这个解构申明,想在一个函数中返回多个结果,就可以申明一个简单的数据类来返回了,然后取值也很方便。

data class KotlinBean(val name: String, val age: Int)

fun main(args: Array<String>) {
    var bean: KotlinBean = KotlinBean("zhangSan", 20)
    var (name, age) = bean //多重赋值
     println("$name,$age")
    //给name赋值其实是调用的bean.component1(),给age赋值调用的是component2()函数
}

zhangSan,20

3.Kotlin中定义data class类需要注意的地方有哪些?

Kotlin中可以创建一个只包含数据的类,称之为数据类,使用关键字data定义

数据类需要满足以下条件

  • 主构造函数至少包含一个参数
  • 所有的主构造函数的参数必须标识为val或var
  • 数据类不可以声明为abstract、open、sealed和inner的
  • 数据类不能继承其他类,但可以实现接口
  • 使用data修饰的数据类,Kotlin会默认帮我们生成getter/setter,copy,toString(),hashCode,equals等方法

data修饰的类并没有无参构造方法,并且该类名是final修饰的 Kotlin中提供了两个插件来解决这两个问题,allOpen是为了去除final修饰,noArg是为了添加无参构造方法。

密封类

1.什么是密封类?

密封类用来表示受限的类继承结构:当一个值为有限几种的类型, 而不能有任何其他类型时。在某种意义上,他们是枚举类的扩展.

2.如何声明一个密封类?

声明一个密封类,使用 sealed 修饰类,密封类可以有子类,但是所有的子类都必须要内嵌在密封类中。

sealed class Animal

fun main(args: Array<String>) {
    say(Dog())
    say(Cat())
}

fun say(animal: Animal) {
    //密封类的好处就在于:使用when表达式时,如果能覆盖所有情况是不需要添加else子句的
    when (animal) {
        is Dog -> animal.yell()
        is Cat -> animal.wow()
    }
}

class Dog : Animal() {
    fun yell() {
        println("wangwangwang")
    }
}

class Cat : Animal() {
    fun wow() {
        println("miaomiaomiao")
    }
}

wangwangwang
miaomiaomiao

3.密封类与枚举类的区别?

枚举类的每个枚举常量只存在一个实例,

密封类的一个子类可以有可包含状态的多个实例!

4.密封类的特点

密封类的所有子类都必须与密封类在同一文件中

密封类子类的子类(间接继承者)可以放在任何位置,无需在同一个文件中

枚举类

java中的枚举类使用enum代替class声明,每一个枚举值代表一个类的实例。

在Kotlin中,枚举类的声明是在class前边加上enum关键字

fun main(args: Array<String>) {
    printAllValues<Color>() //输出RED,GREEN,BLUE
    println(getChinese(Color.YELLOW))
}


/**
 * 枚举类的使用
 * 枚举类常量用逗号分隔,每个枚举常量都是一个对象
 * */
enum class Color {
    RED, YELLOW, BLUE, BLACK, WHITE
}

//自 Kotlin 1.1 起,可以使用 enumValues() 和 enumValueOf() 函数以泛型的方式访问枚举类中的常量 
inline fun <reified T : Enum<T>> printAllValues() {
    println(enumValues<T>().joinToString { it.name })
}

fun getChinese(color: Color) =
        when (color) { //when是一个有返回值的表达式
            Color.BLACK -> "红"
            Color.BLUE -> "蓝"
            Color.RED -> "红"
            Color.WHITE -> "白"
            Color.YELLOW -> "黄"
        }

RED, YELLOW, BLUE, BLACK, WHITE
黄

猜你喜欢

转载自blog.csdn.net/qq_37982823/article/details/87934221