Kotlin-小抄(四)类与面向对象编程
原创
©著作权归作者所有:来自51CTO博客作者wx5ba8dc11102bc的原创作品,请联系作者获取转载授权,否则将追究法律责任
声明类
空类
- 使用class关键字声明类,可以声明一个空类(什么都不干)
声明类和构造函数
- 在Kotlin中可以在声明类的同时声明构造函数,声明构造函数直接在类名的后面使用括号将构造函数的参数列表包含即可
// 通常使用这种
class Person(var name : String, var age :Int, var sex : String) { // 声明类和构造函数
override fun toString(): String {
return "Person (name = $name, age=$age, sex=$sex)"
}
}
@Test
fun testClass() {
val person = Person("Wjx", 22, "M")
println("person =${person}")
}
// 使用次级构造器
class Person() { // 无参的主构造函数
lateinit var name : String // 延迟初始化
var age : Int = 0 // lateinit关键字不能修饰primitive类型
lateinit var sex : String
// 次级构造函数
constructor(name:String, age:Int, sex:String) :this() {
this.name = name
this.age = age
this.sex = sex
}
override fun toString(): String {
return "Person (name = $name, age=$age, sex=$sex)"
}
}
@Test
fun testClass() {
val person = Person()
// 调用主构造器
person.name = "Wjx"
person.age = 22
person.sex = "M"
println("person =${person}")
}
接口和抽象类
抽象类
- Kotlin和Java在接口和抽象类相同
- 但在Kotlin中复写抽象类中的非抽象方法要在抽象类的非抽象方法前加open
- 继承原则
- 当子类继承了某个类之后,便可以使用父类中的成员变量,但并不是完全继承父类的所有成员变量。
- 具体的原则如下:
- 能够继承父类的public和protected成员变量;
- 不能继承父类的private成员变量;
- 对于父类的包访问权限成员变量,如果子类和父类在同一个包下,则子类能够继承;否则,子类不能继承;
- 对于子类可以继承的父类成员变量,如果在子类中出现了同名称的成员变量,则会发生隐藏现象,即子类的成员变量会屏蔽掉父类的同名成员变量。如果要在子类中访问父类中的同名成员变量,需要使用super关键字进行引用。
接口
Object对象
- 因为Kotlin中没有静态属性和方法,所以当我们需要使用单例模式创建实例对象的时候,就需要使用object声明一个object单例对象
object User {
val name : String = "Wjx"
val pwd : String = "Wjx"
fun login() {
println("Hello $name")
}
}
@Test
fun testObject() {
println(User.name)
User.login() // 与静态类调用方式一致
}
- Kotlin中还提供了伴生对象, 使用companion object关键字声明
- 伴生对象也是用来代替静态变量的,一个类只能有一个伴生对象,该类的多个对象共享这个伴生对象
- 伴生对象相当于对Java的类加载机制中init()的封装
class DataBase(var id: Int) {
fun run() {
work()
println("$id is running")
}
// 使用companion object声明伴生对象
companion object DataBaseProcessor {
fun work() {
println("Processor is Working")
}
}
}
@Test
fun testCompanion() {
DataBase(1).run()
DataBase(2).run()
// Processor is Working
// 1 is running
// Processor is Working
// 2 is running
}
数据类
- Java中一般我们写Bean类包含了大量的setter\getter方法
- 而在Kotlin中只需要创建如下的代码就可以避免样板代码
data class UserBean(val username :String, val password : String)
- 主构造函数至少包含一个参数
- 参数必须标识为val或者var
- 不能为abstract、open、sealed或者inner
- 不能继承其他类(但可以实现接口)
- 数据类可以在解构声明中使用
val user = UserBean("Wjx", "Wjx")
val (username, password) = user
Pair和Triple
- Kotlin提供了Pair和Triple数据类,分别表示二元组和三元组对象
@Test
fun pairToMap() {
val map = mapOf(1 to 'A', 2 to 'B', 3 to 'C')
println(map) // 创建的是LinkedHashMap类型的Map
}
枚举
- Kotlin中使用enum class关键字类声明一个枚举类
内部类
普通嵌套类
Kotlin中类可以嵌套,一个类可以嵌套在其它类中,而且可以嵌套多层
class NestClass {
class OutClass {
val id :Int = 0
class NestClass {
fun getOut() {
println(id) // 不可访问
}
}
}
}
- 访问嵌套类的方式是直接使用类名来访问,有多少层嵌套,就用多少层类名来访问
- 普通嵌套类没有持有外部类的引用,所以是无法访问外部类变量的
嵌套内部类
- 在内部类的前面加inner,内部类就会持有外部类的引用
class NestClass {
class OutClass {
val id :Int = 0
inner class NestClass {
fun getOut() {
println(id) // 可以访问
}
}
}
}
访问方式:NestCall.OutClass().Inner().getOut()
匿名内部类
class NestClass {
class OutClass {
var isRunning = false
fun doRun() {
Thread(object : Runnable {
override fun run() {
isRunning = true
println(Thread.currentThread().id)
}
}).start()
}
// 直接使用Lambda表达式
fun doStop() {
Thread({
isRunning = false
println(Thread.currentThread().id)
}).start()
}
// 使用匿名内部类,使用lambda实现run接口
fun doWait() {
val wait = Runnable {
isRunning = false
println(Thread.currentThread().id)
}
Thread(wait).start()
}
// 直接声明一个Lambda函数
fun doNotify() {
val wait = {
isRunning = false
println(Thread.currentThread().id)
}
Thread(wait).start()
}
}
}
@Test
fun testNest() {
NestClass.OutClass().doRun()
NestClass.OutClass().doStop()
NestClass.OutClass().doWait()
NestClass.OutClass().doNotify()
println(Thread.currentThread().state)
}