安卓系列之 kotlin 基础知识(五)

125 阅读1分钟

嵌套类

  1. 嵌套类不能访问外部类的属性,相当于 Java 中的静态内部类,通过类直接调用
  2. 标记为 inner 的嵌套类能够访问其外部类的成员,通过对象调用
//嵌套类
class AndroidEngineer {

    class Computer(var softerName: String) {
        fun doWork() = print("使用 $softerName 软件工作")
    }
}

fun testAndroid() {
    AndroidEngineer.Computer("AndroidStudio").doWork()
}


//内部类
class IosEngineer {
    private val name: String = "ios工程师"

    inner class AppleComputer(var softerName: String) {
        //标记为 inner 的嵌套类能够访问其外部类的成员
        fun doWork() = print("$name 使用 $softerName 工作")
    }
}

fun testIos() {
    IosEngineer().AppleComputer("Xcode").doWork()
}


//匿名内部类
class Button {
    private var onItemClickListenerA: OnItemClickListener? = null
    fun setOnItemClickListener(onItemClickListener: OnItemClickListener) {
        onItemClickListenerA = onItemClickListener
    }
}

interface OnItemClickListener {
    fun onClick()
}

fun test() {
    val button = Button()
    button.setOnItemClickListener(object : OnItemClickListener {
        override fun onClick() {
            print("点击了按钮")
        }

    })
}

数据类

需要满足的条件

  1. 主构造函数需要至少有一个参数;
  2. 主构造函数的所有参数需要标记为 val 或 var;
  3. 数据类不能是抽象、开放、密封或者内部的;

特点

  1. 重写了 equals(),hash(),toString(),所以==比较的是内容
  2. copy(),拷贝一个对象
  3. 自动生成解构,component 函数
  4. 在类体中声明的属性不会在 toString()、 equals()、 hashCode() 以及 copy() 中用到,所以拷贝或者比较不会受这个属性影响
//数据类
data class Cup(var color: String, var material: String) {
    //类内部属性
    var birth: Int = 1900
}

fun testCup() {

    //==比较的是内容,因为数据类重写了equals方法
    //===比较的是引用
    print(Cup("红色""陶瓷") == Cup("红色""陶瓷"))//true
    print(Cup("红色""陶瓷") === Cup("红色""陶瓷"))//false

    val cup = Cup("绿色""陶瓷")

    //copy拷贝对象
    val cupTwo = cup.copy(color = "黄色")

    //直接引用解构
    print("${cup.color} 的颜色的杯子是用 ${cup.material} 做的")

    //类内部属性不影响比较
    val cupA = Cup("红色""陶瓷")
    val cupB = Cup("红色""陶瓷")
    cupA.birth = 1901
    cupB.birth = 1902
    print(cupA == cupB) //true
}

枚举类

  1. 枚举也是类
  2. 默认有 2 个属性
    ordinal(枚举常量的顺序,从 0 开始)
    name(枚举常量的名字)
  3. 默认有 2 个方法:
    values() ----获取所有枚举常量 valueOf() ----获取对应枚举常量
class Place(val x: Intval y: Int) {

}

enum class Direction(private val inPlace: Place) {
    EAST(Place(10)),
    SOUTH(Place(01)),
    NORTH(Place(0, -1)),
    WEST(Place(-10));

    //定义函数
    fun updateDirection(place: Place) = Place(inPlace.x + place.x, inPlace.y + place.y)
}

fun testDirection() {
    print(Direction.EAST.updateDirection(Place(100100)))

    print(Direction.EAST.ordinal)//0
    print(Direction.EAST.name)//EAST

    print(Direction.EAST)

    //values() 遍历
    Direction.values().forEach {
        //名字
        print(it.name)
        //顺序
        print(it.ordinal)
    }

    //valueOf() 若没有找到,则抛出 IllegalArgumentException 异常。
    print(Direction.valueOf("EAST"))
}

//枚举类
enum class Class {
    MATH,
    ENGLISH,
    CHINESE;
}


//代数数据类型ADT
fun testClass(className: Class): String {
    return when (className) {
        Class.MATH -> "数学"
        Class.ENGLISH -> "英语"
        Class.CHINESE -> "中文"
    }
}

//匿名枚举类
enum class ProtocolState {
    WAITING {
        override fun signal() = TALKING
    },

    TALKING {
        override fun signal() = WAITING
    };

    abstract fun signal(): ProtocolState
}

密封类

  1. 表示受限的类继承结构,密封类是枚举类的扩展
  2. 使用关键字 sealed
  3. 所有子类都必须在与密封类自身相同的文件中声明
  4. 抽象的
  5. 不允许有非 private 构造函数
//封闭类
sealed class MyDialogOpera {
    object Show : MyDialogOpera()
    object Hide : MyDialogOpera()
    class TranslateX(val x: Float) : MyDialogOpera()
}

fun execute(view: View, opera: MyDialogOpera) = when (opera) {
    MyDialogOpera.Show -> view.visibility = View.VISIBLE
    MyDialogOpera.Hide -> view.visibility = View.GONE
    is MyDialogOpera.TranslateX -> view.translationX = opera.x
}

抽象类

和 Java 的抽象类一样

//抽象类
abstract class Computer(val name: String) {
    //抽象方法
    abstract fun runSoftware()

    fun withMouse(mouseName: String) {
        print("$name 配置 $mouseName 鼠标")
    }

    //open表示该方法可以被子类实现
    open fun withKeyBoard(keyBoardName: String) {
        print("$name 配置 $keyBoardName 键盘")
    }
}

class WindowComputer : Computer("window电脑") {
    //重写方法
    override fun runSoftware() {
        print("运行软件")
    }


    override fun withKeyBoard(keyBoardName: String) {
        super.withKeyBoard(keyBoardName)
        print($keyBoardName ")
    }
}

fun testComputer() {
    val computer: Computer = WindowComputer()
    computer.runSoftware()
    computer.withMouse("罗技鼠标")
    computer.withKeyBoard("一般键盘")
}

接口

  1. 一个类或者对象可以实现一个或多个接口
  2. 在接口中声明的属性是抽象的,必须在类或者对象中实现
//接口
interface Runnable {
    fun run()
}

interface Eat {

    fun eat(food: String)

    //接口已实现,则子类可以不实现
    fun eatWith() {
        print("兔子用手吃饭饭...")
    }
}

interface Wear {
    val cloth: String
}

//一个类或者对象可以实现一个或多个接口
class Rabbit : RunnableEatWear {
    //属性必须实现
    override val cloth: String = "粉色小裙子"

    override fun run() {
        print("兔子跑起来了...")
    }

    override fun eat(food: String) {
        print("兔子在吃 $food")
    }

    override fun eatWith() {
        super.eatWith()
    }
}

fun testRabbit() {
    val rabbit = Rabbit()
    rabbit.run()
    rabbit.eat("胡萝卜")
    rabbit.eatWith()
}

项目 github 地址

github.com/ElaineTaylo…

若帅哥美女对该系列文章感兴趣,可微信搜索公众号(木子闲集)关注更多更新文章哦,谢谢~