前言
??通過上一篇的Kotlin介紹了一些基本的變量煞聪,方法鸠澈,函數(shù),類等的基本講解层释,接下來婆瓜,讓我們更近一步的學習,深入一點的知識
1.??枚舉類和擴展
1.1?枚舉類
??Kotlin的枚舉類和Java的非常相似贡羔,具有類的特性廉白,一般會將可枚舉的同類型一組值作為枚舉類定義,由于每一枚舉都是個對象,可能在性能上還是不推薦用乖寒,Android中已經(jīng)用注解慢慢取代了猴蹂,這種枚舉的使用
1.1.1 枚舉類的基本用法
??在kotlin中,枚舉類型是以類的形式存在的楣嘁,因此成為枚舉類
enum class Direction {
NORTH,SOUTH,WEST,EAST
}
1.1.2 枚舉值指定對應的數(shù)值
??從下面的代碼可以看出磅轻,除了基本的語法不同,實現(xiàn)的規(guī)則和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. WEST
Log.i("tag",dir1.name)//輸出的是:WEST
Log.i("tag",dir1.ordinal.toString()) //輸出的是在枚舉中的位置 1
Log.i("tag",dir1.toString()) //輸出的是傳入的數(shù)值
Log.i("tag",Direction.valueOf("WEST").toString()) //輸出的是傳入的數(shù)值
//如果要得到所有枚舉的值逐虚,可以使用values的方法
for(d in Direction.values()){
println(d)
}
1.2?擴展
??擴展是Kotlin中非常重要的功能聋溜,可以在沒有源代碼的情況下向類中添加成員,也可以啊子團隊開發(fā)的情況下叭爱,通過擴展撮躁,將模塊分散給多個人開發(fā)
1.2.1 擴展原生API
Kotlin的原生的集合擴展
//這個方法放哪里呢?一般都放在Kotlin文件頂層买雾,當然把曼,也可以放在調(diào)用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("牛逼吧W⒂!型雳!嘻嘻") //這個是上面自己寫的一個方法
1.2.2 擴展自定義類
??擴展類的目的很多当凡,除了系統(tǒng)類需要擴展之外,我們自己編寫的類有時候也需要擴展纠俭,但是我們有不想去類里面修改沿量,這時候這個功能就相得益彰
open class Parent(val va1: Int, val va2: Int) {//使用open聲明,才能允許其他類繼承
var mVal1 = va1
var mVal2 = va2
fun 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 = 3
par2.log()//父類:1 +2 = 3
chil1.log()//子類:1 -2 = -1
open class Parent(val va1: Int, val va2: Int) {
var mVal1 = va1
var mVal2 = va2
fun add() = this.mVal1 + this.mVal2
//內(nèi)部成員函數(shù)冤荆,和擴展同名朴则,擴展覆蓋不了內(nèi)部
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 = 3
par2.log()//父類:自己1 +2 = 3
chil1.log()//父類:自己1 +2 = 3
??上面可以看出:(1)盡管par2的實例對象是Child,但是通過擴展的方法钓简,并沒有重寫父類的擴展方法乌妒,因此par2調(diào)用的還是父類的方法。
(2)類內(nèi)部成員函數(shù)和通過擴展添加的成員函數(shù)沖突外邓,那么內(nèi)部成員函數(shù)的優(yōu)先級更高撤蚊,通過擴展無法覆蓋內(nèi)部成員函數(shù)
1.2.3 擴展伴隨對象
??如果類中有伴隨對象(由于Kotlin類不支持靜態(tài)成員變量,因此引入了伴隨對象损话,來解決類沒有靜態(tài)成員所帶來的尷尬)侦啸,那么可以利用擴展對象添加成員
class SubClass {
companion object {
}
}
fun SubClass.Companion.nihao(){
Log.i("tag","hello word!")
}
SubClass.nihao();//不需要實例,直接類名調(diào)用
//擴展范圍丧枪,放大
//在類中也可以使用擴展
2.??數(shù)據(jù)類和封裝
??數(shù)據(jù)類和封裝是Kotlin中兩種特殊的類光涂,前者用于描述數(shù)據(jù)和相應的操作,后者相當于枚舉類的擴展拧烦,用于描述有限的數(shù)據(jù)
2.1?數(shù)據(jù)類
??數(shù)據(jù)類是Kotlin 的一個語法糖忘闻,Kotlin編譯器會自動為數(shù)據(jù)類生產(chǎn)一些成員函數(shù),以提高開發(fā)效率
2.1.1 使用數(shù)據(jù)類
//一般的類的書寫
class User(var name: String, var sex: Int) {
var mName = name
var mSex = sex
override 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關(guān)鍵字就行了
data class Student(var name: String) {
constructor():this("sdfdf")//為了添加一個無參的構(gòu)造函數(shù)
}
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
??數(shù)據(jù)類和普通的類最大的不同提针,就是數(shù)據(jù)類可以根據(jù)構(gòu)造器的參數(shù)自動生成相關(guān)的代碼;如果Kotlin中曹傀,同事具有普通類辐脖,以及存儲和管理數(shù)據(jù)的功能,建議直接使用數(shù)據(jù)類
編寫數(shù)據(jù)類注意事項
(1)主構(gòu)造器至少有一參數(shù)
(2)主構(gòu)造器的參數(shù)必須標記為var/val
(3)數(shù)據(jù)類不能是抽象類皆愉,open類嗜价,封閉類(sealed)類或內(nèi)部類(inner)
由于主構(gòu)造器必須要有一個參數(shù),不可能存在沒有參數(shù)的主構(gòu)造器幕庐,要想擁有久锥,兩種方案解決:
(1)為主構(gòu)造器每個參數(shù)都加上默認值
data class User(val name :String="Bill", var age :Int = 10)
(2)添加一個沒有參數(shù)的構(gòu)造器,調(diào)用主構(gòu)造器時异剥,指定默認參數(shù)
data class User(var name : String ,var age :Int){
//次構(gòu)造函數(shù)
constructor():this("Devin","18")
}
2.1.2 數(shù)據(jù)類成員的解構(gòu)
??數(shù)據(jù)類成員解構(gòu)瑟由,這里關(guān)鍵解構(gòu),也就是解除結(jié)構(gòu)冤寿,在數(shù)據(jù)類中歹苦,用屬性表示數(shù)據(jù),這些屬性屬于同一數(shù)據(jù)類督怜,要想使用這些屬性,必須首先引用數(shù)據(jù)對象蚪腋,這里的解構(gòu)就是指將這些數(shù)據(jù)對象的屬性提取出來究流,分別單獨賦值給變量
var student = Student("大家好")
val (name) = student
Log.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?泛型基礎(chǔ)
??所謂的泛型节榜,就是指在定義數(shù)據(jù)結(jié)構(gòu)時,只指定類型的占位符别智,等到使用該數(shù)據(jù)結(jié)構(gòu)時在指定具體的數(shù)據(jù)類型
class Box<T>(t :T){
var value = t
}
var box = Box<Int>(1)
Log.i("tag", ";;;;;;" + box.value);
3.2?類型變異
??Kotlin泛型并沒有提供通配符,取而代之的是out和in的關(guān)鍵字(1)用out聲明的泛型占位符只能用在獲取泛型類型值的地方(2)用in聲明的泛型只能在設(shè)置泛型類型值的地方
(1). 使用out關(guān)鍵字
abstract class Source< out T> {
abstract fun NextT(): T
}
fun demo(strs: Source<String>) {
//編譯通過讳窟,因為T是一個out類型參數(shù)
val ni: Source<Any> = strs
}
(1).使用in關(guān)鍵字
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?泛型函數(shù)
fun <T> single(item :T) :T{
return item
}
var single = single(1)
Log.i("tag", ";;;;;;" + single);
3.4?泛型約束
??最常見的約束是上界(upper bound),與Java的extends關(guān)鍵字相同,如果沒有指定丽啡,默認使用的上界類型Any?,在定義泛型參數(shù)的尖括號內(nèi),只允許定義唯一一個上界改执,要是多個就的使用where
fun <T :Parent> convert(item :T){
}
fun<T>clone (list:List<T>,there:T):List<T> where T :Comparable,T:Cloneable{
//.....
}
總結(jié)
??通過本章節(jié)的學習坑雅,了解到了枚舉類,數(shù)據(jù)類霞丧,封閉類,泛型后豫,而且學到了非常方便的一個擴展的實用語法突那,可以很方便的為原生Api以及其他類擴充方法,比較靈活方便愕难,也希望此篇幅的知識對你有稍許的幫助