kotlin封裝

kotlin類型兼容java類型的所有語義和概念,可是也並不是徹底相同,不過在kotlin中,一個類型於java中的同樣,也包含以下元素:java

  • 構造器和初始化模塊
  • 成員函數
  • 屬性
  • 內部類
  • 對象聲明

構造函數

構造函數其實並非一個真正的函數,由於它沒有返回值類型,連函數名也被嚴格約束。而從編譯器的角度看,構造函數的確不是函數,由於編譯器一般會對構造函數進行特別處理,在C++中,構造函數會被處理成內存分配指令,在java中,會被處理成new指令。所以構造函數能夠被看着一個語法糖層面的僞函數。數組

  • 構造函數聲明
//直接在類型名稱後面緊跟參數列表,完成的構造函數定義,叫主構造函數
//只須要一行就實現了屬性定義和構造函數的聲明,比java簡潔太多
//顯示的聲明瞭有參主構造函數,就會覆蓋默認的無參構造函數
class SharedBike (var name:String,var color:Int) {
    //kotlin 將init塊,添加進了 構造函數中的
    init {
        println("在構造函數中,進行一點別的邏輯功能")
    }
     var price:Int = 0
    //二級構造函數 必須 間接或者直接代理 主構造函數 this(), 其實這也正是kotlin源程序中以 .kt 結尾的類型聲明要添加括號的緣由
    constructor(name: String,color: Int,price:Int):this(name,color){
        this.price = price
    }
}

fun main() {
    val sharedBike = SharedBike("哈羅",0xff0000)
    println(sharedBike.name)
    println(sharedBike.color)
}
  • 構造函數的權限聲明
class SharedBike private constructor(var name: String, var color: Int) {
    var price: Int = 0

    //次級構造函數聲明訪問權限,直接在constructor關鍵字前添加就能夠了
    public constructor(name: String, color: Int, price: Int) : this(name, color) {
        this.price = price
    }
}

fun main() {
    //主構造函數被聲明爲私有,就只能調用次級構造函數了 ,主構造函數聲明訪問權限,必須添加關鍵字 constructor
    val sharedBike = SharedBike("哈羅", 0xff0000, 256)
    println(sharedBike.name)
    println(sharedBike.color)
}
  • 初始化順序
class Animal() {
    //聲明時初始化
    var name:String = getName()
    constructor(name:String):this(){
        println("構造函數時初始化")
        this.name = name
    }
    init {
        name = "name_from_init"
        println("init 塊中初始化")
    }

    fun printName(){
        println("name = $name")
    }
}

fun getName():String{
    println("聲明時初始化。。。")
    return "name_from_declare"
}

fun main() {
    val animal = Animal("name_from_constructor")
    animal.printName()
}

結果:安全

聲明時初始化。。。 init 塊中初始化 構造函數時初始化 name = name_from_constructoride

事實上之因此是這樣一個順序,於JVM虛擬機實例化對象的整體策略有關,當JVM實例化Animal時,會依次執行以下邏輯: 1 在路徑下找到 Animal.class 2 在JVM的heap內存域(即堆區)爲Animal實例分配足夠的內存空間。 3 將Animal實例內存空間清零,將其實例對象內的各個基本類型的字段都設置爲對應的默認值。 4 若是字段在聲明時進行了初始化,則按順序執行各個字段的初始化邏輯 5 若是定義init{}塊,則執行init{}塊中的邏輯 6 若是定義了構造函數,則執行構造函數中的邏輯函數

屬性

屬性String 和String? 是不一樣的,因此 屬性String的值不能賦值給 String?this

class Animal() {
    //聲明屬性 直接賦值
    var name = "張三"
    //聲明一個能夠爲空的屬性, 添加了 ? 表示這個屬性能夠爲null,不然屬性不能爲空值
    var height:Int? = null
    //強制 設置一個屬性爲空 , 會報錯
//    var weight :String = null!!
    //聲明一個abstract的屬性,能夠不用賦值,可是對應的其所在的類 必須也是 abstract 修飾的
    // abstract var hobby:String
}
  • 屬性的空安全
class Animal {
    var name:String?= null
    fun test(){
       name?.let {
           println(it)
       }
        println(name?.length)
    }
}

fun main() {
    val animal = Animal()
    animal.test()
    animal.name = "小白兔"
    println("-----------賦值後------------------")
    animal.test()
}

結果:設計

null 可控屬性不加let塊 執行爲空,加了let塊 與if 判斷同樣 -----------賦值後------------------ 小白兔 3代理

訪問權限

kotlin 中頂級變量和類屬性默認狀況下的訪問權限都是public。這一點與java徹底不一樣,java中默認狀況下都是private。code

class Animal {
    var name:String = "二哈"
        private set //設置賦值方法爲private
}

fun main() {
    val animal = Animal()
    //賦值報錯
    animal.name = "sldfk"
}

數組

kotlin 的大部分語法特性都是基於java的,編寫習慣也沒有太大變化,而數組是個例外。對象

數組的初始化

  • 經過Array接口聲明數組
//聲明一個 大小爲3,初始值都是0的數組 ,"it->"能夠省略
var asc = Array(3,{it -> 0})
  // 若是不想kotlin自動推斷類型,能夠在聲明數組的時候顯示標記
var asc:Array<Int> = Array(3) { 0}
// array 也能夠根據步長來 初始化值
var asc:Array<Int> = Array(3) { it * 2}
  • 數組讀寫
val asc:Array<Int> = Array(3) { it * 2}
    //寫數組
    asc[0] = 12
    asc.set(1,24)
    //讀數組
    val a = asc[0]
    val b = asc.get(1)
  • 聲明一個引用類型數組
class Animal(val name:String,age:Int) {
    var age:Int = age
    override fun toString(): String {
        return "dog name = $name, age = $age,height = ${age * 2}"
    }
}

fun main() {
    val asc = Array(3) { Animal(it.toString(),it + 1)}
    for (a in asc){
        println(a.toString())
    }
    /**
     * dog name = 0, age = 1,height = 2
    dog name = 1, age = 2,height = 4
    dog name = 2, age = 3,height = 6
     */
}
  • 其餘聲明數組的方式
fun main() {
    //聲明一個Animal 類型的大小爲5的數組,可是沒有對數組元素進行初始化,元素都爲null
    val asc = arrayOfNulls<Animal>(5)
    //聲明一個Int類型的數組,大小爲3,默認初始值爲0,其餘基本類型也可使用相似的方法進行初始化
    val arr = IntArray(3)
    for (i in asc) println(i)
    //聲明java中的包裝類型,(做參數傳入須要包裝類型的java方法中時,會自動裝箱)
    val array = arrayOfNulls<Int>(2)
    array[0] = 12
    array[1] = 2
}
  • 多維數組
//聲明一個二維數組,以下聲明瞭一個2行三列的數組
    val asc = Array(2){Array(3){0} }
    //遍歷多維數組
    for (i in asc.indices){
        for (j in asc[i].indices){
            println("i = $i,j = $j")
        }
    }
    //讀寫多維數組
    asc[0][2] = 12
    val asc02 = asc[0][2]
    println(asc02)
    //聲明一個引用類型的多維數組
    val an = Array(3){ arrayOfNulls<Animal>(3) }
  • 數組與列表轉換 在實際開發中列表的使用大於數組,由於列表的長度能夠動態改變,數組不行。
val asc = IntArray(3)
    asc[0] = 12
    asc[1] = 16
    asc[2] = 19
    val array2list = asc.asList() 
    for (e in array2list){
        println(e)
    }

    //聲明一個列表
    val list = ArrayList<Int>(2)
    list.add(1)
    list.add(2)
    list.add(3)
    for (e in list){
        println(e)
    }
    //將列表轉成數組
    val ints =  list.toArray()
    for (i in ints.indices) println(i)

靜態函數和伴隨對象

kotlin中的類不像java中的類,沒有靜態方法和靜態變量,在kotlin類中編寫的函數和屬性,必須經過類實例對象才能訪問,而不能直接經過類名訪問。kotlin 特別設計了"伴隨對象"。伴隨對象顧名思義是一個對象聲明,要定義一個伴隨對象很簡單,經過 companion object 關鍵字定義,實例以下:

class Animal() {
    var name:String? = null
    //聲明一個伴隨對象 InnerAnimal,並在其中定義函數run(),
    // 從外面能夠直接經過Animal類型先到名 做爲前綴調用該伴隨對象的方法
    companion object InnerAnimal{
        fun run(){
            println("fun run running .......")
        }
    }
  //一個類中 只能定義一個伴隨對象
  //伴隨對象的名稱能夠省略,好比這裏的 InnerAnimal 能夠不寫
//    companion object {
//        fun run(){
//            println("fun run running .......")
//        }
//    }
}

fun main() {
    Animal.run()
}
  • 伴隨對象 由於是一個對象聲明,因此不能實例化
  • 伴隨對象中的屬性 在伴隨對象中,不只能夠聲明方法,也能夠定義變量。所定義的變量也能夠經過伴隨對象的宿主類直接訪問,看起來就像java類中的靜態變量同樣
class Animal() {
    var name:String? = null
    companion object InnerAnimal{
        var speed = 20
        fun run(){
            println("fun run running speed = $speed")
        }
    }
}

fun main() {
    Animal.run()
    Animal.speed = 50
    Animal.run()
}
  • 伴隨對象的初始化 伴隨對象沒有構造函數,可是能夠給伴隨對象添加 init{} 塊,init塊繪製實例化伴隨對象所在類,或者第一次調用伴隨對象的時候執行。
  • 伴隨對象的原理 以上面的Animal類爲例子,通過編譯器編譯以後,speed變量就變成了 Animal類中的靜態變量,伴隨對象InnerAnimal 也是Animal類中的一個靜態變量了。kotlin中所謂的伴隨對象,其實就是一個普通的變量,可是這個變量有其不普通之處,那就是其變量名與伴隨對象名稱徹底相同,看起來像一個類名,一樣,InnerAnimal變量的訪問限定符包括static,所以能夠 Animal.InnerAnimal 這樣訪問伴隨對象
  • 匿名類
open class Animal(val name:String) {
    open fun run(){
        println("$name run........")
    }
}

fun main() {
    val a = object {
        init {
            println("init ..........")
        }
        //不像java中匿名類,只能調用父類(實現接口)的方法
        //能夠直接在 匿名類中 聲明方法
        fun print() {
            println("a.print()......")
        }
    }
    a.print()

    //匿名類 也能夠實現接口 或者 繼承某個基類
    val dog = object :Animal("二哈"){
        override fun run(){
            println("dog $name is running ...")
        }
    }

    dog.run()
}

init .......... a.print()...... dog 二哈 is running ...

相關文章
相關標籤/搜索