嵌套类
- 嵌套类不能访问外部类的属性,相当于 Java 中的静态内部类,通过类直接调用
- 标记为 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("点击了按钮")
}
})
}
数据类
需要满足的条件
- 主构造函数需要至少有一个参数;
- 主构造函数的所有参数需要标记为 val 或 var;
- 数据类不能是抽象、开放、密封或者内部的;
特点
- 重写了 equals(),hash(),toString(),所以==比较的是内容
- copy(),拷贝一个对象
- 自动生成解构,component 函数
- 在类体中声明的属性不会在 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
}
枚举类
- 枚举也是类
- 默认有 2 个属性
ordinal(枚举常量的顺序,从 0 开始)
name(枚举常量的名字) - 默认有 2 个方法:
values() ----获取所有枚举常量 valueOf() ----获取对应枚举常量
class Place(val x: Int, val y: Int) {
}
enum class Direction(private val inPlace: Place) {
EAST(Place(1, 0)),
SOUTH(Place(0, 1)),
NORTH(Place(0, -1)),
WEST(Place(-1, 0));
//定义函数
fun updateDirection(place: Place) = Place(inPlace.x + place.x, inPlace.y + place.y)
}
fun testDirection() {
print(Direction.EAST.updateDirection(Place(100, 100)))
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
}
密封类
- 表示受限的类继承结构,密封类是枚举类的扩展
- 使用关键字 sealed
- 所有子类都必须在与密封类自身相同的文件中声明
- 抽象的
- 不允许有非 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("一般键盘")
}
接口
- 一个类或者对象可以实现一个或多个接口
- 在接口中声明的属性是抽象的,必须在类或者对象中实现
//接口
interface Runnable {
fun run()
}
interface Eat {
fun eat(food: String)
//接口已实现,则子类可以不实现
fun eatWith() {
print("兔子用手吃饭饭...")
}
}
interface Wear {
val cloth: String
}
//一个类或者对象可以实现一个或多个接口
class Rabbit : Runnable, Eat, Wear {
//属性必须实现
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()
}