一、簡介
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))
}