kotlin基礎知識總結(jié)

目錄:
一.環(huán)境搭建
二.基礎語法
1.函數(shù)定義
2.可變參數(shù)
3.定義常量與變量
4.NULL檢查機制
5.類型轉(zhuǎn)換
三.基本類型
1.數(shù)字型习贫,Number(包含整數(shù)和浮點等)
2.布爾型(Boolean)
3.數(shù)組
4.字符串
5.判斷兩個對象相等
四.條件語句
1.If
2.When
五.循環(huán)語句
1.for
2.While和do while
3.返回和跳轉(zhuǎn) (continue return break)
4.標簽
六.類和對象
1.類聲明
2.創(chuàng)建類
3.類構(gòu)造器
4.抽象類
5.嵌套類
6.內(nèi)部類
7.類的修飾符
8.類中屬性的set,get方法
七.繼承
1.kotlin的超類
2.繼承的基本實現(xiàn)
3.對構(gòu)造函數(shù)的處理
4.屬性重寫
八. 接口
九. 泛型
十. 枚舉
十一.數(shù)據(jù)類
十二.密封類

一. 環(huán)境搭建(基于android studio 3.0):

  • 安裝kotlin插件:
    路徑:file---setting---plugins—Browers Repositories--輸入框輸入kotlin--點擊install(as3.0默認安裝)
  • 項目gradle中加入
    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version
buildscript {
    ext.kotlin_version = '1.1.51'
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.0.1'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}
  • module的gradle中加入
    apply plugin: 'kotlin-android'
    apply plugin: 'kotlin-android-extensions'
    dependencies之中加入:compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    整體如下
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
    compileSdkVersion 26
    defaultConfig {
        applicationId "kotlin.com.kotlindemo"
        minSdkVersion 19
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:26.1.0'
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
    compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}

二. 基礎語法

1. 函數(shù)定義:

  • <作用域> fun <函數(shù)名>(<參數(shù)>):<返回參數(shù)>{ 函數(shù)主體 }
  • 例子:
private fun sum(a : Int , b : Int) : Int{
    return a+b
}
  • 表達是作為函數(shù)主體不翩,返回類型自動推斷:
    例子:
public fun sum(a : Int , b : Int) = a + b

2.可變參數(shù):

函數(shù)的變長參數(shù)可以用 vararg 關(guān)鍵字進行標識:
例子:

fun vars(vararg v : Int){
    for ( vt in v){
        print(vt)
    }
}

3. 定義常量與變量:

var <標識符> :<類型> = <初始化值>
val <標識符> :<類型> = <初始化值>
var : 代表當前參數(shù)為可變參數(shù)
val : 代表當前參數(shù)為不可變參數(shù)鸠澈,只可以進行一次賦值狈定。類似于java中的final
例子:

val a : Int = 0
val b = 0
var c : Int = 0
c += 1

4. NULL檢查機制:

相比java粗梭,kotlin在創(chuàng)建變量和傳入變量的時候斟珊,就提供了可空相關(guān)的標識符

  • ? :芦瘾?在標識符后使用鸳粉,代表對象可為空扔涧,如果當前對象為空,不會拋出空指針異常赁严。而是會返回null
  • H拍! :代表當前變量或常量一定不能為空疼约。如果為空卤档,就拋出空指正異常
  • 例子:
// 可為空 
var age : String? = null
// 可為空,如果age為空程剥,返回null
var age1 = age?.toInt()
// 不能為空
var age2 = age!!.toInt()

5. 類型轉(zhuǎn)換

  • Java中劝枣,判斷類型使用instanceof
  • Kotlin中,使用is
fun getStringLength(obj : Any): Int? {
    if(obj is String){
        // 進行is判斷以后织鲸,會自動轉(zhuǎn)化成obj
        return obj.length
    }
    if(obj !is String){
        return null
    }
    return null
}

三. 基本類型

1. 數(shù)字型舔腾,Number(包含整數(shù)和浮點等)

  • Byte(8位) 、Short(16位)搂擦、Int(32位)稳诚、Long(64位)、Float(32位)瀑踢、Double(64位)
  • 表現(xiàn)形式:
    十進制:123 十六進制:0x123 二進制:0b123 長整型:123L 備注:不支持八進制
  • 類型轉(zhuǎn)換:
    所有的數(shù)字類型都支持以下的方法進行類型轉(zhuǎn)換:
    toByte(): Byte
    toShort(): Short
    toInt(): Int
    toLong(): Long
    toFloat(): Float
    toDouble(): Double
    toChar(): Char
  • 例子:
//正確的例子:
val b: Byte = 1 
val i: Int = b.toInt() 
//錯誤的例子:
val b: Byte = 1 // OK, 字面值是靜態(tài)檢測的
val i: Int = b // 錯誤

2. 布爾型(Boolean)

和java一致扳还,不做贅述

3. 數(shù)組

創(chuàng)建數(shù)組的兩種方式:
var intArr : IntArray = intArrayof(0,1,2)
var intArr2 : Array<Int> = arrayof(0,1,2)

4. 字符串

  • 定義
    var str : String = “str”
  • striing轉(zhuǎn)int
Java : var strToInt : Int = Integer.parseInt(str)
Kotlin : var strToInt : Int = str.toInt()
  • int 轉(zhuǎn) String
var int : Int = 0
str = int.toString();
  • 對于字符串的substring, indexOf, replace等方法,和原方法完全一致橱夭。
    下面專門介紹幾個Kotlin新增和修改的字符串使用方法
    1. Split方法氨距,相比java,kotlin的split方法更靈活,直接返回List集合
      例子:Java : char[] charStr = str.split()
      Kotlin: val listString : List<String> = str.split(".")
    2. 因為Kotlin允許直接通過下標訪問指定位置的字符棘劣,所以如果想要獲取當前字符俏让。串一個位置的值,只用以下兩種方法即可
      例子:
    var str : String = “str”
    var s : String = str[i].toString()
    s = str.get(0).toString()
    
  • kotlin字符串拼接
    Java在字符串拼接這一塊,幾乎每次都要使用+去進行處理首昔。不易于閱讀寡喝,同時編寫復雜。
    Kotlin在這一塊進行了改進勒奇,很大程度上為開發(fā)者節(jié)省了大量時間拘荡。
    var moneySum : Int = 5
    var str : String = “今天撿到${moneySum}塊錢”
    str = “字符串長度為${str.length}”
    

5. 判斷兩個對象相等

  • Java中,判斷兩個對象的地址撬陵,或者兩個對象是否相等,分別使用equals和==网缝。
  • kotlin中巨税,稍微做了一點改動,kotlin中的==等同于java中的equals粉臊,kotlin中的===等同于java中的==草添。

四. 條件語句

1. If:

  • if的使用和java上基本相同。這里強調(diào)一個if在kotlin之中的擴展功能扼仲。
    擴展功能:if條件語句可以支持直接返回對象远寸。具體例子如下:
  • 例子:
val x = 5
val y = 6
val a = if(x > y) 5 else 6

2. When:

著重強調(diào)一下when。在kotlin之中屠凶,大家會發(fā)現(xiàn)找不到switch了驰后。因為switch被when給替代了〈@ⅲ可想而知灶芝,when的地位有多高了吧。下面介紹一下when的用法唉韭。

  • 基本用法:when 將它的參數(shù)和所有的分支條件順序比較夜涕,直到某個分支滿足條件。when 既可以被當做表達式使用也可以被當做語句使用属愤。如果它被當做表達式女器,符合條件的分支的值就是整個表達式的值,如果當做語句使用住诸, 則忽略個別分支的值驾胆。
  • 類似于switch的用法:
    我們知道switch只能制定一種特定類型,并且相對于每一個case的條件判斷只能是相等只壳。但是對于when俏拱,同樣擁有可配置的case。但是case的判斷條件完全由自己去控制吼句。相比switch锅必,極大得增加了擴展性。
  • 例子:
    fun whenFun(x : Int){
       when(x){
        1-> print("1")
        2-> print("2")
        in 1..4 -> print("在1和4之間")
        4,5->print("4或者5")
        else -> print("none") // else類似switch中的default
      }
    }
    

五. 循環(huán)語句

1. for:

for循環(huán)可以便利所有實現(xiàn)迭代器(iterator)的對象,介紹幾種實現(xiàn)方式

  • 最基本搞隐,類似java中的foreach :
for(item in collection){
      print(item)
    }
}
  • 便利的時候驹愚,僅獲取索引,實現(xiàn)如下:
for(i in array.indices){
    array[i] // i是索引值
}
  • 便利的時候劣纲,同時獲取索引和key
for((index,value) in array.withIndex()){
    value = array[index]
}

2. While和do while

實現(xiàn)和java完全一致逢捺,不做贅述。
例子:

while( 布爾表達式 ) {
  //循環(huán)內(nèi)容
}
do {
                 //代碼語句
}while(布爾表達式);

3. 返回和跳轉(zhuǎn) (continue return break)

使用方式和java完全一致癞季,簡單介紹

  • return劫瞳。默認從最直接包圍它的函數(shù)或者匿名函數(shù)返回。
  • break绷柒。終止最直接包圍它的循環(huán)志于。
  • continue。繼續(xù)下一次最直接包圍它的循環(huán)废睦。

4. 標簽

好了伺绽,本節(jié)重頭戲來了。標簽是一個非常好用的東西嗜湃。他可以讓我們在多循環(huán)嵌套的情況下奈应,進行穿插處理。不會像java一樣购披,continue杖挣,break只能針對當前循環(huán)。那么讓我們來體驗下標簽吧刚陡。

  • 標簽介紹:
    在 Kotlin 中任何表達式都可以用標簽(label)來標記程梦。 標簽的格式為標識符后跟 @ 符號,例如:abc@橘荠、fooBar@都是有效的標簽屿附。 要為一個表達式加標簽,我們只要在其前加標簽即可哥童。
  • 例子
fun labelDemo(){
    val intArr = intArrayOf(0,1,2)
    val intArr2 = intArrayOf(0,1,2)
    Log.i(TAG,"start for")
    intArrFor@for (int in intArr){
        Log.i(TAG,"for intArr int : $int")
        intArr2For@for (int2 in intArr2){
        // 每一次退出挺份,回到intArrFor
            if(int2 == 1) break@intArrFor
            Log.i(TAG,"for intArr2 int2 : $int2")
        }
    }
    Log.i(TAG,"end for")
}

備注:暫時缺失對標簽在return應用的介紹,講真贮懈,小編自己還沒搞明白示括。搞明白以后再加上來废酷。

六. 類和對象

1. 類聲明

class <類名稱> {
    // 函數(shù)
    fun foo(){}
    }
}

2. 創(chuàng)建類

class Student{
    val name = “小明”
    val age = 5
}
// 創(chuàng)建類
val stu = Student()
stu.name
stu.age

3. 類構(gòu)造器

kotlin中類分成主構(gòu)造器和次構(gòu)造器搁吓。一個類可以有主構(gòu)造器和多個次構(gòu)造器蝴光。

  • 主構(gòu)造器:
    主構(gòu)造器不包含任何初始化代碼,只有請求參數(shù)抡医,如下
class Preson constructor(name : String , age : Int){

}

如果主構(gòu)造器沒有任何注解躲因,也沒有任何可修飾符早敬,那么constructor可以隱藏

class Person(name : String , age : Int){

}
  • 次構(gòu)造器:
    1. 沒有主構(gòu)造器的情況
    class ClassSample{
        var age = 0
        constructor(name: String , age : Int) {
            this.age = age
      }
    }
    
    1. 有主構(gòu)造器的情況
    class ClassSample(name : String) {
        var age = 0
        constructor(name: String , age : Int) : this(name){
            this.age = age
      }
    }
    
  • 對于需要初始化的參數(shù),我們使用關(guān)鍵詞init進行處理大脉,如下
class Person (name : String){
    val personName : String = name
    init{
      personName = name
    }  
}

4. 抽象類

  • open關(guān)鍵字搞监,所有類和方法默認都是final。所以如果需要當前類可繼承镰矿,方法可覆蓋琐驴,需要將當前方法和類加上open。抽象類默認加上open秤标,不需要再加一遍
  • 例子:
open class Base(){
    open fun baseFun(){}
}
abstract class Child() : Base(){
    abstract fun baseFun(){}
}

5. 嵌套類

嵌套類引用不了外部類的成員绝淡,這和Java類似,相當于隱式的外部類苍姜。但是在實現(xiàn)上和java略有差異够委。
java:通過在內(nèi)部類中加上一個static,說明這是嵌套類怖现。
kotlin:在類的內(nèi)部再創(chuàng)建一個類的時候,如果加任何修飾符玉罐,那么就是嵌套類屈嗤。
例子

class Outer{
    val a = “”
    // 嵌套類
    class Inner{
        fun foo(){
        }
    }
}

6. 內(nèi)部類

kotlin內(nèi)部類需要使用關(guān)鍵字inner來表示。相比嵌套類吊输,內(nèi)部類可以使用外部類的引用饶号。從而訪問外部類的屬性和方法等。
例子

class Outer{
  val a = ""
  /**
  * inner標記一個類是內(nèi)部類
  * 可以引用外部類的成員
  * 采用this@類名方式季蚂,獲取到外部類的this對象
  */
  inner class inner{
       fun foo(){
          val innerA = this@Outer.a
       }
   }
}

7. 類的修飾符

  • 權(quán)限修飾符
    1. public 所有情況都可以訪問
    2. internal 針對同一模塊
    3. protected 包權(quán)限茫船,針對同一文件和子類
    4. private僅針對當前文件
      特別說明:
      1.同一模塊比較抽象,以前在java中沒有遇到過扭屁,這里說的是同一個module算谈。
      2.如果不對方法或者類增加權(quán)限修飾符,那么默認是public料滥。
  • 類和方法屬性標識符
    1. abstract 抽象類
    2. enum枚舉類(java中只需要enum然眼,kotlin中需要enum class)
    3. final 不可繼承(默認屬性)
    4. open 修飾后,類可被繼承葵腹,方法可被重寫(abstract 默認帶open)

8.類中屬性的set,get方法

set和get在很多教程里都會被放在類的屬性里作為一個小點來講高每。為什么小編要單獨拿出來。我相信很多人如果沒有接觸過property践宴。都會跟小編有一樣一頭霧水鲸匿,所以小編認為有必要再專門說明一下。

  • 先看一下java對set和get的實現(xiàn)
class Student{
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
// 所以阻肩,一般設置一個參數(shù)带欢,都用以下方式實現(xiàn)。
Student stu = new Student();
stu.setName("小明");
  • 再看一下kotlin的實現(xiàn)方式
class Student{
    val name = ""
}
// 設置參數(shù)
val stu = Student()
stu.name = "小明"

看到這里,肯定會有很多小伙伴會有疑問洪囤。java如果把參數(shù)的權(quán)限變成public也可以用和kotlin一樣的方式徒坡。但是小編在這里告訴你,不要太天真瘤缩。來讓我們看一看喇完,在我們使用kotlin設置參數(shù)的時候他,kotlin偷偷背著我們做了什么剥啤。

  • 屬性聲明的完整語法:
    var <propertyName> [ : propertyType ] [ = <property_initializer> ]
    [<getter>]
    [<setter>]
    set和get都是可選的锦溪。當我們默認使用類似kotlin的實現(xiàn)方式stu.name = 小明的時候,其實是調(diào)用了默認的setter方法府怯。當然val聲明不允許實現(xiàn)setter方法刻诊。
class Student {

    var name : String = "小豆"
    get() = field + "啦啦啦"
    set(value) {
        field = value + "拉拉"
    }
    
    val age = 10
    set(value) {} // 會報錯

}

七. 繼承

1. kotlin的超類

所有的kotlin都繼承Any這個類,算是kotlin中所有類的超類牺丙。但他不是object则涯,可以理解成object在java中的地位。

  • Any默認提供了以下三個方法
equals()

hashCode()

toString()
  • 相比較而言冲簿,java中的object則提供了以下這些方法
toString()

equals()

hashCode()

getClass()

clone()

finalize()

notify()

notifyAll()

wait()

wait(long)

wait(long,int)  

2. 繼承的基本實現(xiàn)

類需要加上關(guān)鍵字open粟判,因為類是默認final的。同時抽象類默認加上open
例子:

open class Base(age : Int)

class Child(age : Int) : Base(age){}

3. 對構(gòu)造函數(shù)的處理

  • 如果子類有構(gòu)造函數(shù)
    如果子類有主構(gòu)造函數(shù)峦剔, 則基類必須在主構(gòu)造函數(shù)中立即初始化档礁。
// 父類
open class Base(name : String , age : Int){
}
// 子類
class Child(name : String , age : Int, no : Int) : Base(name , age){
}
// 測試
fun main(args: Array<String>) {
    val s =  Child("小豆", 18,10)
    println("學生名: ${s.name}")
    println("年齡: ${s.age}")
    println("學生號: ${s.no}")
}
  • 子類沒有構(gòu)造函數(shù)
    如果子類沒有主構(gòu)造函數(shù)吝沫,則必須在每一個二級構(gòu)造函數(shù)中用 super 關(guān)鍵字初始化基類呻澜,或者在代理另一個構(gòu)造函數(shù)。初始化基類時惨险,可以調(diào)用基類的不同構(gòu)造方法羹幸。
open class Base(name : String) {

    constructor(name : String , age : Int) : this(name){

    }

}

class Student : Base{

    constructor(name : String) : super(name){
        
    }
    
}

4. 屬性重寫

屬性重寫和函數(shù)繼承一樣。需要在屬性前加上關(guān)鍵字open辫愉。屬性重寫使用 override 關(guān)鍵字睹欲,屬性必須具有兼容類型,每一個聲明的屬性都可以通過初始化程序或者getter方法被重寫:
例子

open class Base {

    open val name = ""

    open fun base(){
        print("父類Base")
    }

}

open class Student : Base() {

    override val name: String
        get() = super.name

    override fun base() {
        print("子類base")
    }

}

八. 接口

Kotlin 接口與 Java 8 類似一屋,使用 interface 關(guān)鍵字定義接口窘疮,允許方法有默認實現(xiàn)

  • 接口定義
interface InterDemo {

    fun foo(){ }

}
  • 接口實現(xiàn)
class Child : InterDemo{
    override  fun foo(){
    }
}
  • 接口屬性
    kotlin的接口屬性和java有一定差異。
    1. kotlin:接口中的屬性只能是抽象的冀墨,不允許初始化值闸衫,接口不會保存屬性值,實現(xiàn)接口時诽嘉,必須重寫屬性蔚出。
    2. java:接口中的成員變量只能是public final static 弟翘。
    interface InterDemo {
        var name : String
        fun foo()
    }
    
    class Child : InterDemo {
        override var name: String = "" //子類必須重寫接口的屬性
        override fun foo() { }
    }
    
  • 函數(shù)重寫
    和類繼承一樣,需要在函數(shù)前加上open(函數(shù)默認被final修飾)
open class Base {
    open fun base(){
        print("父類Base")
    }
}

open class Student : Base() {
    override fun base() {
        print("子類base")
    }
}

fun main(args: Array<String>) {
    val s =  Student()
    s.base();
}
// 輸出結(jié)果
子類base

由于kolin中接口中的函數(shù)是可以有初始化代碼的骄酗,所以就遇到了繼承和實現(xiàn)的接口和類中稀余,包含同一個函數(shù)名的情況。我們需要使用super<類名>.<方法名>來選擇調(diào)用
例子:

open class A {
    open fun base(){ }
}

interface B {
    fun base(){ }
}

class C() : A() , B {
    override fun base() {
        super<A>.base()
        super<B>.base()
    }
}

九. 泛型

泛型趋翻,即 "參數(shù)化類型"睛琳,將類型參數(shù)化,可以用在類踏烙,接口师骗,方法上。與 Java 一樣讨惩,Kotlin 也提供泛型辟癌,為類型安全提供保證,消除類型強轉(zhuǎn)的煩惱荐捻。

  • 聲明一個泛型
class Person<T>(t : T) {
    val value = t
}
  • 創(chuàng)建一個泛型
val person = Person<String>("小豆")
  • 定義泛型類型變量黍少,可以完整地寫明類型參數(shù),如果編譯器可以自動推定類型參數(shù)处面,也可以省略類型參數(shù)厂置。
val person = Person("小豆")
  • 函數(shù)中聲明泛型,類型參數(shù)要放在函數(shù)名的前面
 fun <T> box(value : T){
        print(value)
}
//以下全都合法
val box1 = box("小豆1")
val box2 = box<String>("小豆2")
  • 型變
    高能預警TЬ!這是小編看到暫時比較隱澀的一個知識點患蹂。
    生產(chǎn)者與消費者

在 Java 泛型里或颊,有通配符這種東西,我們要用 ? extends T 指定類型參數(shù)的上限传于,用 ? super T 指定類型參數(shù)的下限囱挑。Kotlin 拋棄了這個系統(tǒng),引用了生產(chǎn)者和消費者的概念沼溜。

什么是生產(chǎn)者平挑?生產(chǎn)者是那些只能 讀取 數(shù)據(jù)的對象;
什么是消費者系草?消費者是那些只能 寫入 數(shù)據(jù)的對象通熄;
要理解這個概念,我們可以看一個例子:

public interface Collection<E> extends Iterable<E> {
  boolean add(E e);
  boolean addAll(Collection<? extends E> c);
}

這是 Collection 接口的add() 和 addAll() 方法找都,傳入它們的類型參數(shù)一個是 E 唇辨,一個是 ? extends E,為什么呢能耻?這兩個方法之間不就是批量操作的區(qū)別嗎赏枚?為什么一個只接受 E 類型的參數(shù)亡驰,另一個卻接受 ? extend E 的類型?

這是因為饿幅,Java 泛型是不型變的凡辱,也就是說,雖然 String 類型是 Object 類型的子類型栗恩,但 Collection<String> 并不是 Collection<Object> 的子類型透乾。

對于一個 Collection<Object> 來說,因為 String 是 Object 的子類型摄凡,一個 String 對象就是 Object 類型续徽,所以可以直接把它添加入 Collection<Object> 里,add() 方法的類型參數(shù)因為可以設為 E亲澡;而想把 Collection<String> 添加入 Collection<Object> 時钦扭,因為 Java 泛型不型變的原因,就會出現(xiàn)編譯錯誤床绪,必須用 ? extends E 將 Collection<String> 囊括到 Collection<Object> 里客情。

從另一個角度看,對于一個 Collection<A>癞己,我們從其中讀取出一個對象膀斋,這個對象可以是 A 的子類型,也可以是 A 類型痹雅,這種特性叫 協(xié)變(Convariant)仰担;而要向 Collection<A> 寫入一個對象時,我們既可以寫入一個 A 類型對象绩社,也可以寫入 A 的父類型摔蓝,這種特性叫 逆協(xié)變(contravariance),協(xié)變和逆協(xié)變都是類型安全的愉耙。

從這個角度來說贮尉,我們可以把那些只能保證讀取數(shù)據(jù)時類型安全的對象叫做生產(chǎn)者,用 out T 標記朴沿;把那些只能保證寫入數(shù)據(jù)安全時類型安全的對象叫做消費者猜谚,用 in T 標記。

如果你覺得太晦澀難懂赌渣,就這么記吧:out T 等價于 ? extends T魏铅,in T 等價于 ? super T,此外還有 * 等價于 ?坚芜。

聲明處型變
Kotlin 對 Java 泛型最大的改動就是添加了聲明處型變沦零。看下面的例子:

interface Source<T> {
  T nextT();
}

void demo(Source<String> str) {
  // Java 中這種寫法是不允許的
  Source<Object> obj = str;
  /*...*/
}

因為 Java 泛型是不型變的货岭,Source<String> 不是 Source<Object> 的子類型路操,所以不能把 Source<String> 類型變量賦給 Source<Object> 類型變量疾渴。

現(xiàn)在用 Kotlin 改寫上面的接口聲明:

interface Source<out T> {
  T nextT();
}

我們在接口的聲明處用 out T 做了生產(chǎn)者聲明,因為這個接口只有一個讀取數(shù)據(jù)的 nextT() 方法屯仗,可以視為生產(chǎn)者搞坝。把這個接口的類型參數(shù)聲明為生產(chǎn)者后,就可以實現(xiàn)安全的類型協(xié)變了:

fun demo(Source<String> str) {
  val obj: Source<Any> = str // 合法的類型協(xié)變
  /*...*/
}

十. 枚舉

  • 枚舉基本用法
    枚舉的用法和java基本一致魁袜。枚舉類最基本的用法是實現(xiàn)一個類型安全的枚舉桩撮。枚舉常量用逗號分隔,每個枚舉常量都是一個對象。
  • 聲明枚舉類
    java中聲明枚舉類只需要用關(guān)鍵字enum修飾峰弹。kotlin之中需要使用enum class來修飾店量。
enum class Color {
    RED,BLUE,GREEN
}
  • 枚舉初始化
enum class Color(value : Int) {
    RED(100),BLUE(200),GREEN(200)
}
  • 使用枚舉常量
    Kotlin 中的枚舉類具有合成方法,允許遍歷定義的枚舉常量鞠呈,并通過其名稱獲取枚舉常數(shù)融师。
Color red = Color.valueOf("RED");
Color[] values = Color.values();

十一.數(shù)據(jù)類

  • 數(shù)據(jù)類介紹
    數(shù)據(jù)類是kotlin獨有的,幫我們封裝了許多方法來存儲和展示數(shù)據(jù)蚁吝。對于我們平時需要展示的model來說旱爆,用數(shù)據(jù)類最合適不過。
  • 數(shù)據(jù)類創(chuàng)建
    使用data關(guān)鍵詞來修飾class
    例子:
data class User(val name : String , var age : Int)
  • data類會自動提取以下函數(shù)(如果這些函數(shù)在類中已經(jīng)被明確定義了窘茁,或者從超類中繼承而來怀伦,就不再會生成。)
    1.equals() / hashCode()
    2.toString() 格式如 "User(name=John, age=42)"
    3.componentN() functions 對應于屬性山林,按聲明順序排列
    4.copy() 函數(shù)
  • 所需滿足的條件
    1.主構(gòu)造函數(shù)至少包含一個參數(shù)房待。
    2.所有的主構(gòu)造函數(shù)的參數(shù)必須標識為val 或者 var ;
    3.數(shù)據(jù)類不可以聲明為 abstract, open, sealed 或者 inner;
    4.數(shù)據(jù)類不能繼承其他類 (但是可以實現(xiàn)接口)。
  • Copy函數(shù)
    類似于java中的clone()驼抹,但是比clone()更靈活
    例子
//創(chuàng)建data類
data class User(name : String , age : Int)
val user = User("aaa",12)
// 拷貝過程中重新賦值
val userChangeCopy = user.copy(name = "小豆")
fun copy(name: String = this.name, age: Int = this.age) = User(name, age)

十二.密封類

  • 介紹:密封類類似于枚舉類桑孩,可以當成是枚舉類的擴展。相比枚舉類只能定義一個實例砂蔽。密封類可以定義多個實例洼怔。
  • 聲明密封類
    聲明一個密封類署惯,使用 sealed 修飾類左驾,密封類可以有子類,但是所有的子類都必須要內(nèi)嵌在密封類中极谊。
    sealed 不能修飾 interface ,abstract class(會報 warning,但是不會出現(xiàn)編譯錯誤)
sealed class Expr
data class Const(val number: Double) : Expr()
data class Sum(val e1: Expr, val e2: Expr) : Expr()
object NotANumber : Expr()

fun eval(expr: Expr): Double = when (expr) {
    is Const -> expr.number
    is Sum -> eval(expr.e1) + eval(expr.e2)
    NotANumber -> Double.NaN
}
  • 優(yōu)點
    使用密封類的關(guān)鍵好處在于使用 when 表達式 的時候诡右,如果能夠 驗證語句覆蓋了所有情況,就不需要為該語句再添加一個 else 子句了轻猖。
fun eval(expr: Expr): Double = when(expr) {
    is Expr.Const -> expr.number
    is Expr.Sum -> eval(expr.e1) + eval(expr.e2)
    Expr.NotANumber -> Double.NaN
    // 不再需要 `else` 子句帆吻,因為我們已經(jīng)覆蓋了所有的情況
}

暫未了解清楚:
1.屬性重寫
2.標簽return用法
3.約束泛型
4.型變
5.星號投射
6.密封類
7.數(shù)據(jù)類
待補充:
1.委托
2.擴展

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市咙边,隨后出現(xiàn)的幾起案子猜煮,更是在濱河造成了極大的恐慌次员,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,651評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件王带,死亡現(xiàn)場離奇詭異淑蔚,居然都是意外死亡,警方通過查閱死者的電腦和手機愕撰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評論 3 392
  • 文/潘曉璐 我一進店門刹衫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人搞挣,你說我怎么就攤上這事带迟。” “怎么了囱桨?”我有些...
    開封第一講書人閱讀 162,931評論 0 353
  • 文/不壞的土叔 我叫張陵仓犬,是天一觀的道長。 經(jīng)常有香客問我蝇摸,道長婶肩,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,218評論 1 292
  • 正文 為了忘掉前任貌夕,我火速辦了婚禮律歼,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘啡专。我一直安慰自己险毁,他們只是感情好,可當我...
    茶點故事閱讀 67,234評論 6 388
  • 文/花漫 我一把揭開白布们童。 她就那樣靜靜地躺著畔况,像睡著了一般。 火紅的嫁衣襯著肌膚如雪慧库。 梳的紋絲不亂的頭發(fā)上跷跪,一...
    開封第一講書人閱讀 51,198評論 1 299
  • 那天,我揣著相機與錄音齐板,去河邊找鬼吵瞻。 笑死,一個胖子當著我的面吹牛甘磨,可吹牛的內(nèi)容都是我干的橡羞。 我是一名探鬼主播,決...
    沈念sama閱讀 40,084評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼济舆,長吁一口氣:“原來是場噩夢啊……” “哼卿泽!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起滋觉,我...
    開封第一講書人閱讀 38,926評論 0 274
  • 序言:老撾萬榮一對情侶失蹤签夭,失蹤者是張志新(化名)和其女友劉穎齐邦,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體第租,經(jīng)...
    沈念sama閱讀 45,341評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡侄旬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,563評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了煌妈。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片儡羔。...
    茶點故事閱讀 39,731評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖璧诵,靈堂內(nèi)的尸體忽然破棺而出汰蜘,到底是詐尸還是另有隱情,我是刑警寧澤之宿,帶...
    沈念sama閱讀 35,430評論 5 343
  • 正文 年R本政府宣布族操,位于F島的核電站,受9級特大地震影響比被,放射性物質(zhì)發(fā)生泄漏色难。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,036評論 3 326
  • 文/蒙蒙 一等缀、第九天 我趴在偏房一處隱蔽的房頂上張望枷莉。 院中可真熱鬧,春花似錦尺迂、人聲如沸笤妙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蹲盘。三九已至,卻和暖如春膳音,著一層夾襖步出監(jiān)牢的瞬間召衔,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評論 1 269
  • 我被黑心中介騙來泰國打工祭陷, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留苍凛,地道東北人。 一個月前我還...
    沈念sama閱讀 47,743評論 2 368
  • 正文 我出身青樓颗胡,卻偏偏與公主長得像毫深,于是被迫代替她去往敵國和親吩坝。 傳聞我的和親對象是個殘疾皇子毒姨,可洞房花燭夜當晚...
    茶點故事閱讀 44,629評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 前言 人生苦多,快來 Kotlin 钉寝,快速學習Kotlin弧呐! 什么是Kotlin闸迷? Kotlin 是種靜態(tài)類型編程...
    任半生囂狂閱讀 26,201評論 9 118
  • 前言 最先接觸編程的知識是在大學里面腥沽,大學里面學了一些基礎的知識,c語言鸠蚪,java語言今阳,單片機的匯編語言等;大學畢...
    oceanfive閱讀 3,068評論 0 7
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理茅信,服務發(fā)現(xiàn)盾舌,斷路器,智...
    卡卡羅2017閱讀 134,652評論 18 139
  • 1. Java基礎部分 基礎部分的順序:基本語法蘸鲸,類相關(guān)的語法妖谴,內(nèi)部類的語法,繼承相關(guān)的語法酌摇,異常的語法膝舅,線程的語...
    子非魚_t_閱讀 31,623評論 18 399
  • 相信許多人都用過下面這種卡埂息,卻不一定知道它也有有效期吧琳轿。 昨天晚上去國光超市購物,聽到有人在總臺與...
    職業(yè)敬仰者閱讀 925評論 0 0