Kotlin的解析(中)
前言
??通過上一篇的Kotlin介紹了一些基本的變量,方法,函數,類等的基本講解,接下來,讓我們更近一步的學習,深入一點的知識
1.??枚舉類和擴展
1.1?枚舉類
??Kotlin的枚舉類和Java的非常相似,具有類的特性,一般會將可枚舉的同類型一組值作為枚舉類定義,由于每一枚舉都是個對象,可能在性能上還是不推薦用,Android中已經用注解慢慢取代了,這種枚舉的使用
1.1.1 枚舉類的基本用法
??在kotlin中,枚舉類型是以類的形式存在的,因此成為枚舉類
enum class Direction { NORTH,SOUTH,WEST,EAST } 復制代碼1.1.2 枚舉值指定對應的數值
??從下面的代碼可以看出,除了基本的語法不同,實現的規則和Java的非常相似
enum class Direction private constructor(val d:Int){ SOUTH(1),WEST(2);override fun toString(): String {return d.toString()} }fun main(args:Array<String>){ var dir1 : Direction = Direction. SOUTH var dir2 = Direction. WEST println(dir1)//輸出的是1 println(dir2)//輸出的是2 } 復制代碼1.1.3 枚舉的其他拓展
var dir1 : Direction = Direction. WESTLog.i("tag",dir1.name)//輸出的是:WESTLog.i("tag",dir1.ordinal.toString()) //輸出的是在枚舉中的位置 1Log.i("tag",dir1.toString()) //輸出的是傳入的數值Log.i("tag",Direction.valueOf("WEST").toString()) //輸出的是傳入的數值//如果要得到所有枚舉的值,可以使用values的方法 for(d in Direction.values()){ println(d) } 復制代碼1.2?擴展
??擴展是Kotlin中非常重要的功能,可以在沒有源代碼的情況下向類中添加成員,也可以啊子團隊開發的情況下,通過擴展,將模塊分散給多個人開發
1.2.1 擴展原生API
Kotlin的原生的集合擴展
//這個方法放哪里呢?一般都放在Kotlin文件頂層,當然,也可以放在調用swap方法的位置前面 fun MutableList<Int>.swap(index1:Int ,index2:Int){//為MutableList添加一個swap的方法,用于交互任意兩個集合元素的位置var tmp = this[index1]this[index1] = this[index2]this[index2] = tmp;}val tab = mutableListOf(1,2,3)tab.swap(0,2) //原生里面是沒有這個方法的,通過擴展就可以了,牛逼Log.i("tag","jihe: " + tab.toString())//輸出[3,2,1]復制代碼JDK標準的集合類ArrayList添加了一個hellow的方法
fun ArrayList<Int>.hellow(string: String){println(string)}var list: ArrayList<Int> = ArrayList();list.add(20)list.add(30)list.add(40)list.add(50)list.swap(0,2)//這個是原生自帶的list.hellow("牛逼吧!!!嘻嘻") //這個是上面自己寫的一個方法 復制代碼1.2.2 擴展自定義類
??擴展類的目的很多,除了系統類需要擴展之外,我們自己編寫的類有時候也需要擴展,但是我們有不想去類里面修改,這時候這個功能就相得益彰
open class Parent(val va1: Int, val va2: Int) {//使用open聲明,才能允許其他類繼承var mVal1 = va1var mVal2 = va2fun add() = this.mVal1 + this.mVal2 }class Child(va1: Int, va2: Int) : Parent(va1, va2) {fun sub() = mVal1 - mVal2 }fun Parent.log() {Log.i("tag", "父類:" + "${mVal1} +${mVal2} = ${add()}")}fun Child.log() {Log.i("tag", "子類:" + "${mVal1} -${mVal2} = ${sub()}")}var par1: Parent = Parent(1, 2)var par2: Parent = Child(1, 2)var chil1: Child = Child(1, 2)par1.log()//父類:1 +2 = 3par2.log()//父類:1 +2 = 3chil1.log()//子類:1 -2 = -1open class Parent(val va1: Int, val va2: Int) {var mVal1 = va1var mVal2 = va2fun add() = this.mVal1 + this.mVal2 //內部成員函數,和擴展同名,擴展覆蓋不了內部 fun log() {Log.i("tag", "父類:自己" + "${mVal1} +${mVal2} = ${add()}")} }fun Parent.log() {Log.i("tag", "父類:" + "${mVal1} +${mVal2} = ${add()}")}fun Child.log() {Log.i("tag", "子類:" + "${mVal1} -${mVal2} = ${sub()}")}var par1: Parent = Parent(1, 2)var par2: Parent = Child(1, 2)var chil1: Child = Child(1, 2)par1.log()//父類:自己1 +2 = 3par2.log()//父類:自己1 +2 = 3chil1.log()//父類:自己1 +2 = 3復制代碼??上面可以看出:(1)盡管par2的實例對象是Child,但是通過擴展的方法,并沒有重寫父類的擴展方法,因此par2調用的還是父類的方法。 (2)類內部成員函數和通過擴展添加的成員函數沖突,那么內部成員函數的優先級更高,通過擴展無法覆蓋內部成員函數
1.2.3 擴展伴隨對象
??如果類中有伴隨對象(由于Kotlin類不支持靜態成員變量,因此引入了伴隨對象,來解決類沒有靜態成員所帶來的尷尬),那么可以利用擴展對象添加成員
class SubClass {companion object {} }fun SubClass.Companion.nihao(){Log.i("tag","hello word!")}SubClass.nihao();//不需要實例,直接類名調用 //擴展范圍,放大 //在類中也可以使用擴展 復制代碼2.??數據類和封裝
??數據類和封裝是Kotlin中兩種特殊的類,前者用于描述數據和相應的操作,后者相當于枚舉類的擴展,用于描述有限的數據 #####2.1?數據類 ??數據類是Kotlin 的一個語法糖,Kotlin編譯器會自動為數據類生產一些成員函數,以提高開發效率
2.1.1 使用數據類
//一般的類的書寫 class User(var name: String, var sex: Int) {var mName = namevar mSex = sexoverride fun equals(other: Any?): Boolean {//重寫,是不是感覺的很不爽,要寫這么多if (other is User) {if (mName == other.mName && mSex == other.mSex) {return true}} else {return false}return false}override fun toString(): String {//重寫,是不是Java中很煩,yes,很煩return "User {name = $mName \n sex = $mSex }"} }復制代碼??從上面User可以看出,只有name和sex是必要的,其余的都可以自動的推倒,而怎么弄呢?其實Kotlin中提供了,那就是在class前面加上data關鍵字就行了
data class Student(var name: String) {constructor():this("sdfdf")//為了添加一個無參的構造函數 }var student = Student("xixi") var student1 = Student("haha") Log.i("tag", student.toString()); //輸出:Student(name=xixi) Log.i("tag", student1.toString());//輸出: Student(name=haha) Log.i("tag", student.equals(student1).toString());//輸出:false 復制代碼??數據類和普通的類最大的不同,就是數據類可以根據構造器的參數自動生成相關的代碼;如果Kotlin中,同事具有普通類,以及存儲和管理數據的功能,建議直接使用數據類
編寫數據類注意事項
(1)主構造器至少有一參數
(2)主構造器的參數必須標記為var/val
(3)數據類不能是抽象類,open類,封閉類(sealed)類或內部類(inner) 由于主構造器必須要有一個參數,不可能存在沒有參數的主構造器,要想擁有,兩種方案解決:
(1)為主構造器每個參數都加上默認值
data class User(val name :String="Bill", var age :Int = 10) 復制代碼(2)添加一個沒有參數的構造器,調用主構造器時,指定默認參數
data class User(var name : String ,var age :Int){ //次構造函數 constructor():this("Devin","18") } 復制代碼2.1.2 數據類成員的解構
??數據類成員解構,這里關鍵解構,也就是解除結構,在數據類中,用屬性表示數據,這些屬性屬于同一數據類,要想使用這些屬性,必須首先引用數據對象,這里的解構就是指將這些數據對象的屬性提取出來,分別單獨賦值給變量
var student = Student("大家好")val (name) = studentLog.i("tag", ";;;;;;"+name );//;;;;;;大家好 復制代碼2.1.3 封閉類
??封閉類也是Kotlin的一個語法糖,可以把它理解為枚舉的擴展,一個封閉類,前面用sealed,可以有任意多個字對象,封閉類的值只能是這些字對象,使用封閉類的好處,主要是與when表達式配合,不需要再使用else形式
sealed class Icon () class Small() : Icon() class Big() : Icon()fun eval(icon: Icon) {when (icon) {is Small -> {}is Big -> {}}}var big = Big()eval(big) 復制代碼3.??泛型
3.1?泛型基礎
??所謂的泛型,就是指在定義數據結構時,只指定類型的占位符,等到使用該數據結構時在指定具體的數據類型
class Box<T>(t :T){var value = t }var box = Box<Int>(1) Log.i("tag", ";;;;;;" + box.value); 復制代碼3.2?類型變異
??Kotlin泛型并沒有提供通配符,取而代之的是out和in的關鍵字(1)用out聲明的泛型占位符只能用在獲取泛型類型值的地方(2)用in聲明的泛型只能在設置泛型類型值的地方
(1). 使用out關鍵字
abstract class Source< out T> {abstract fun NextT(): T }fun demo(strs: Source<String>) { //編譯通過,因為T是一個out類型參數val ni: Source<Any> = strs} 復制代碼(1).使用in關鍵字
abstract class Comparable<in T>{abstract fun comparaTo(other:T) }fun demo (x:Comparable<Number>){ //1.0時Double類型,Double時Number的子類型x.comparaTo(1.0)val y: Comparable<Double> = x } 復制代碼3.3?泛型函數
fun <T> single(item :T) :T{return item}var single = single(1)Log.i("tag", ";;;;;;" + single); 復制代碼3.4?泛型約束
??最常見的約束是上界(upper bound),與Java的extends關鍵字相同,如果沒有指定,默認使用的上界類型Any?,在定義泛型參數的尖括號內,只允許定義唯一一個上界,要是多個就的使用where
fun <T :Parent> convert(item :T){ }fun<T>clone (list:List<T>,there:T):List<T> where T :Comparable,T:Cloneable{ //..... } 復制代碼總結
??通過本章節的學習,了解到了枚舉類,數據類,封閉類,泛型,而且學到了非常方便的一個擴展的實用語法,可以很方便的為原生Api以及其他類擴充方法,比較靈活方便,也希望此篇幅的知識對你有稍許的幫助
總結
以上是生活随笔為你收集整理的Kotlin的解析(中)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ArcGIS for qml - 地址地
- 下一篇: 临床研究和医疗保健行业实现数据湖架构的机