一、简介
Kotlin
中使用关键字class
声明类,后面紧跟类名 。Kotlin
中的类默认是public final
的,所以如果不需要类为final
的时候,需要使用open
关键字修饰类,如果没有声明父类。则父类默认为Any
类。
//定义一个空类
open class Animal
interface Run
//继承类或接口时,使用 : 隔开,父类和接口间使用 , 隔开
class Dog : Animal(), Run
二、构造函数
1. 主构造器
主构造器放在类名后,不能包含任何代码,初始化代码可以放在初始化代码段中,初始化代码段使用init
关键字作为前缀。
注意:
主构造器的参数可以在初始化代码段中使用,可以通过主构造器来定义属性并初始化属性值(可以是var
或val
)。
class Dog constructor(val age: Int, val name: String){
init {
println("Dog $name is $age years old.")
}
}
如果构造器有注解,或者有可见度修饰符,则constructor
关键字是必须的,注解和修饰符放在它之前,否则constructor
可以省略不写。
2. 创建实例
fun main(args: Array<String>) {
val dog = Dog(2,"Irving")
}
3.次级构造函数
类的次级构造函数使用constructor
修饰。
class Cat {
constructor(age: Int, name: String){
println("Cat $name is $age years old")
}
}
如果类有主构造器,则每个次级构造函数都需要直接或间接的代理此主构造器。在同一个类中代理另一个构造函数使用this
关键字。
class Cat(age: Int) {
constructor(age: Int, name: String): this(age){
println("Cat $name is $age years old")
}
constructor(age: Int, name: String, type: Int): this(age, name){
println("Cat $name is $age years old")
}
}
三、访问修饰符
private:
修饰类的时候,表示该类中所有成员都是私有的。修饰成员的时候,表示该成员是该类私有的。protected:
只能用以修改类的成员,表示只有该类和它的子类可以访问该成员。public:
所有类均可访问。internal:
表示只有该模块(moudle
)内的类能访问。
四、伴生对象
通过companion object
声明伴生对象,必须写在一个类的内部,作为该类的伴生对象,编译器编译时会在该类中生成一个静态的Companion
对象,然后调用该静态对象的成员。伴生对象中的属性和方法可以理解为Java
中的静态变量和静态方法,可以直接通过类名.属性/方法
调用,如果是Java
类中调用时通过类名.Companion.属性/方法
调用
class Bird{
companion object {
const val BIRD_NAME = "Irving"
fun getBirdName(): String = BIRD_NAME
}
}
除了使用object
关键字声明一个单例类之外,使用伴生对象可以很方便的创建单例对象。
class Person{
companion object {
fun get(): Person = Holder.instance
}
private object Holder{
val instance = Person()
}
}
五、Kotlin中的动态代理
Kotlin
中通过使用by
关键字可以很方便的使用动态代理。
interface People {
fun sayHello()
}
//目标类
class Man : People {
override fun sayHello() {
println("Hello")
}
}
//代理类
class Irving(people: People) : People by people
fun main(args: Array<String>) {
val irving = Irving(Man())
irving.sayHello()
}
Kotlin
会将动态代理编译为静态代理去调用,所以Kotlin
的动态代理比Java
的动态代理效率高,因为Java
的动态代理本质上是通过反射去调用的。
六、数据类
可以使用data
关键字声明一个数据类,数据类是public final
的,所以不可以被继承(需要继承时可以使用密封类)。编译器会为数据类的所有属性生成getter()/setter()
方法,并且会重写toString()
、hashCode()
、equals()
、copy()
这些方法。
data class User(
var id: Int,
var name: String,
var gender: Int
)
七、密封类
密封类可以理解为一个增强的枚举类,密封类和它的子类必须写在同一个文件中,增强的地方就是密封类的子类可以扩展,从而更加灵活。
sealed class Hello {
object UP : Hello()
object DOWN : Hello()
object LEFT : Hello()
object RIGHT : Hello()
class Irving(var age: Int) : Hello()
}
fun test(hello: Hello) {
when (hello) {
Hello.UP -> println("UP")
Hello.DOWN -> println("DOWN")
Hello.LEFT -> println("LEFT")
Hello.RIGHT -> println("RIGHT")
is Hello.Irving -> println(hello.age)
}
}
fun main(args: Array<String>) {
test(Hello.Irving(11))
}