第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

Kotlin 類和對(duì)象

從這篇文章開始我們一起正式進(jìn)入 Kotlin 面向?qū)ο蟮氖澜?,Kotlin 實(shí)際上也是一門面向?qū)ο蟮恼Z(yǔ)言但同時(shí)又兼顧了函數(shù)式編程語(yǔ)言。只不過函數(shù)在 Kotlin 中的地位被提升至一等公民。但是在 Kotlin 中也是有類、對(duì)象、屬性、方法等。

1. Kotlin 中的類

在 Kotlin 中類和 Java 中概念基本是一致的,都是使用 class 關(guān)鍵字來聲明一個(gè)類,一個(gè)類中可以用屬性表示一個(gè)類的狀態(tài),可以用方法來表示一個(gè)類的行為。但是與 Java 不同的是 Kotlin 中的類聲明默認(rèn)就是 finalpublic , 所以在 Kotlin 中不能直接繼承一個(gè)類,因?yàn)槟J(rèn)類是 final 的,此外也不需要像 Java 中一樣顯式使用 public 修飾符。

//Student.java
public class Student {//public修飾符
    private String name;
    private String nickName;
    private int age;

    public Student(String name, String nickName, int age) {
        this.name = name;
        this.nickName = nickName;
        this.age = age;
    }
}

//SeniorStudent.java
public class SeniorStudent extends Student {//直接繼承Student類
    public SeniorStudent(String name, String nickName, int age) {
        super(name, nickName, age);
    }
}

而在 Kotlin 中不能直接繼承一個(gè)類,如果需要繼承一個(gè)類則需要在基類上加 open 關(guān)鍵字修飾。

 open class Student(
    private val name: String,
    private val nickName: String,
    private val age: Int
)//Student類被繼承需要加open關(guān)鍵字,此外Kotlin中構(gòu)造器初始化也省去了很多模版代碼

class SeniorStudent(
    private val name: String,
    private val nickName: String,
    private val age: Int
) : Student(name, nickName, age)//在Kotlin中繼承不再使用extends關(guān)鍵字而是使用:來替代

2. 類的定義

在 Kotlin 中和 Java 一樣都是使用 class 關(guān)鍵字修飾對(duì)應(yīng)類的名稱即可。在類中會(huì)有屬性描述類的對(duì)象狀態(tài),方法描述類的對(duì)象方法。

class Bird {
    val color: String = "green"//類的屬性描述類的對(duì)象的狀態(tài)
    val age: Int = 3
    
    fun fly() {//類的方法描述類的對(duì)象的行為
      println("I can fly!")
    }
}

我們可以上述 Kotlin 代碼反編譯成 Java 代碼,會(huì)發(fā)現(xiàn)雖然 Kotlin 和 Java 聲明方法基本類似,但是還是存在一些不同的

public final class Bird {//可以看到j(luò)ava中自動(dòng)加上public,進(jìn)一步證明了在Kotlin默認(rèn)是public訪問,而java默認(rèn)是包可見。
    //此外還可看到Bird使用了final修飾,所以也就進(jìn)一步證明Kotlin中默認(rèn)所有都是final修飾,也就意味這個(gè)類默認(rèn)是不能被繼承的。
   @NotNull
   private final String color = "green";//final修飾,是因?yàn)樵贙otlin中使用的是val修飾成員變量,所以可以看到kotlin val就是使用Java中的final實(shí)現(xiàn)的。那么如果使用var修飾就不需要final了。
   private final int age = 3;

   @NotNull
   public final String getColor() {//由于是val修飾,所以color屬性只會(huì)有對(duì)應(yīng)getter方法,沒有setter方法
      return this.color;
   }

   public final int getAge() {
      return this.age;
   }

   public final void fly() {//可以看到fly函數(shù)是final修飾,也就進(jìn)一步證明Kotlin中默認(rèn)所有都是final修飾,那么這個(gè)fly是不能被子類重寫的
      String var1 = "I can fly!";
      boolean var2 = false;
      System.out.println(var1);
   }
}

3. 更簡(jiǎn)單構(gòu)造類的對(duì)象

在 Kotlin 中構(gòu)造對(duì)象不再需要 new 關(guān)鍵字了,而是直接調(diào)用類的構(gòu)造器方法就可以創(chuàng)建一個(gè)對(duì)象了。例如以下代碼:

val bird = Bird() // 省略了new關(guān)鍵字,直接創(chuàng)建Bird對(duì)象

當(dāng)然也可以創(chuàng)建帶參數(shù)的對(duì)象,Kotlin 只需要將上述 Bird 類修改為帶默認(rèn)參數(shù)的構(gòu)造器即可,而在 Java 中則需要增加一個(gè)重載構(gòu)造器函數(shù),但是相比你會(huì)發(fā)現(xiàn) Kotlin 更為方便和簡(jiǎn)潔。
Java 實(shí)現(xiàn):

class Bird {
    private String color;
    private int age;
    public Bird(String color, int age) {
        this.color = color;
        this.age = age;
    }
    
    public void fly() {
        println("I can fly!");
    } 
}

Bird brid = new Bird("blue", 7);//java創(chuàng)建一個(gè)帶參數(shù)Bird對(duì)象

Kotlin 實(shí)現(xiàn):

class Bird(val color: String = "green", val age: Int = 3) {
    fun fly() {
        println("I can fly!")
    }
}

val brid = Bird(color = "blue", age = 7)//創(chuàng)建一個(gè)帶參數(shù)Bird對(duì)象

4. 類的構(gòu)造器函數(shù)

在 Kotlin 中構(gòu)造器函數(shù)是存在 “主從” 關(guān)系,這點(diǎn)是 Java 中不存在的,也就是常說的主構(gòu)造器函數(shù)和從構(gòu)造器函數(shù)。比如在上述 Bird 類中需要新增一個(gè)帶類型 (type) 屬性的構(gòu)造器,就可以定義從構(gòu)造器,從構(gòu)造器是利用 constructor 關(guān)鍵字聲明。

class Bird(val color: String = "green", val age: Int = 3) { //主構(gòu)造器
    constructor(
        color: String = "green",
        age: Int = 3,
        type: String
    ) : this(color, age) {//使用constructor聲明從構(gòu)造器,:this(color, age)從構(gòu)造器直接委托調(diào)用主構(gòu)造器函數(shù)
        //do logical
    }

    fun fly() {
        println("I can fly!")
    }
}

fun main() {
    val smallBird = Bird(color = "blue", age = 8, type = "small")
}

需要注意的是,在 Kotlin 中默認(rèn)類都會(huì)存在一個(gè)無參主構(gòu)造器函數(shù),除非我們手動(dòng)指定。此外如果一個(gè)存在主構(gòu)造器,那么從構(gòu)造器函數(shù)就會(huì)直接或間接委托調(diào)用主構(gòu)造器,直接委托給主構(gòu)造器就類似上述例子中的 : this(color, age) ,當(dāng)然可以通過從構(gòu)造器 A 委托從構(gòu)造器 B,然后從構(gòu)造器 B 委托給主構(gòu)造器,從而達(dá)到間接委托作用。

class CustomView : View {
    constructor(context: Context) : this(context, null)//從構(gòu)造器A委托調(diào)用從構(gòu)造器B
    constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)//從構(gòu)造器B委托調(diào)用從構(gòu)造器C

    constructor(context: Context, attrs: AttributeSet?, defStyle: Int) : super(context, attrs, defStyle) {//從構(gòu)造器C委托調(diào)用主構(gòu)造器

    }
}

5. init 初始化塊

與 Java 不同的是在 Kotlin 中還存在 init 初始化塊的概念,它屬于構(gòu)造器函數(shù)一部分,只是在代碼形式看似兩者是分離的。如果我們需要在初始化時(shí)進(jìn)行其他的額外操作時(shí),這時(shí)候就需要 init 語(yǔ)句塊來執(zhí)行,有個(gè)有趣的點(diǎn)需要注意的是,在 init 初始化塊中,是可以直接訪問構(gòu)造器函數(shù)中參數(shù)的。

class Bird(val color: String = "green", val age: Int = 3) {
  //...
}
//上述代碼實(shí)際上等同于下面代碼
class Bird(color: String = "green", age: Int = 3) {
    val color: String = color
    val age: String = age
}

//所以針對(duì)沒有val修飾構(gòu)造器函數(shù)參數(shù),只能在init初始化塊中訪問,而一般成員函數(shù)是無法訪問的
class Bird(color: String = "green", age: Int = 3) {//當(dāng)color沒有val修飾
    init {
        println("color: $color")//可以看到在init塊中使用構(gòu)造器函數(shù)中的color參數(shù)
    }
    fun printInfo() {
        println(color)//非法訪問
    }
}

對(duì)于 init 初始化塊,是可以存在多個(gè)的,它們執(zhí)行順序是從上到下依次執(zhí)行。

class Bird(color: String = "green", age: Int = 3) {
    init {
        println("color: $color")//init塊1
    }

    init {
        println("age: $age")//init塊2
    }
}    

//執(zhí)行的順序是,先輸出init塊1中日志再輸出init塊2中的日志

對(duì)于 init 初始化塊和從構(gòu)造器同時(shí)存在,它們的執(zhí)行順序是怎么樣的呢?是先執(zhí)行完所有的 init 初始化塊,再執(zhí)行從構(gòu)造器函數(shù)中代碼。
可以上述例子修改一下即可:

class Bird(color: String = "green", age: Int = 3) {
    init {
        println("color: $color")//init塊1
    }

    init {
        println("age: $age")//init塊2
    }

    constructor(color: String, age: Int, type: String) : this(color, age) {
        println("constructor executed")
    }
}

fun main() {
    val smallBird = Bird(color = "blue", age = 8, type = "small")
}

//輸出結(jié)果
color: blue
age: 8
constructor executed
Process finished with exit code 0

6. 類的 setter,getter 訪問器

與 Java 不同的是,需要手動(dòng)創(chuàng)建 setter,getter 方法;即使現(xiàn)在很多 IDEA 插件工具可以自動(dòng)生成,但是從語(yǔ)言層面來說還是比較啰嗦的。所以 Kotlin 直接在語(yǔ)言的層面省去了。先來對(duì)比一下:

public class Bird {
    private String color;
    private int age;
    private String type;

    public Bird(String color, int age, String type) {
        this.color = color;
        this.age = age;
        this.type = type;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }
}

而對(duì)于 Kotlin 只需要簡(jiǎn)單一行即可達(dá)到以上實(shí)現(xiàn):

class Bird(var color: String, var age: Int, var type: String)//var修飾則表示color屬性會(huì)自動(dòng)生成setter,getter方法,如果是val修飾表示只讀,那么只會(huì)生成getter方法

為了進(jìn)一步驗(yàn)證,看看這一行簡(jiǎn)單聲明是否反編譯成 java 代碼是怎么樣的

public final class Bird {
   @NotNull
   private String color;
   private int age;
   @NotNull
   private String type;

   @NotNull
   public final String getColor() {
      return this.color;
   }

   public final void setColor(@NotNull String var1) {
      Intrinsics.checkParameterIsNotNull(var1, "<set-?>");
      this.color = var1;
   }

   public final int getAge() {
      return this.age;
   }

   public final void setAge(int var1) {
      this.age = var1;
   }

   @NotNull
   public final String getType() {
      return this.type;
   }

   public final void setType(@NotNull String var1) {
      Intrinsics.checkParameterIsNotNull(var1, "<set-?>");
      this.type = var1;
   }

   public Bird(@NotNull String color, int age, @NotNull String type) {
      Intrinsics.checkParameterIsNotNull(color, "color");
      Intrinsics.checkParameterIsNotNull(type, "type");
      super();
      this.color = color;
      this.age = age;
      this.type = type;
   }
}

7. 不同訪問控制規(guī)則

7.1 自帶默認(rèn)的 final 修飾

在 Java 中我們經(jīng)常會(huì)控制一個(gè)類不被修改或繼承,則需要 final 修飾符修飾;而在 Kotlin 中不要手動(dòng)添加 final 而是默認(rèn)就是 final ,如果需要讓這個(gè)類或方法被繼承和修改,就需要手動(dòng)添加 open 關(guān)鍵解除這個(gè)禁忌。

open class Animal(color: String, age: Int) {//open關(guān)鍵字打開final禁忌,使得Animal可以被繼承
    open fun printInfo() {//open關(guān)鍵字打開final禁忌,使得printInfo可以被子類重寫
        println("this is animal!")
    }
}

class Dog(color: String, age: Int) : Animal(color, age) {
    override fun printInfo() {
        println("this is dog!")
    }
}

我們也可以通過編譯上述代碼,看 Animal 類是否還存在 final 修飾符,來進(jìn)一步證明我們結(jié)論。

public class Animal {//沒有final可以被繼承
   public void printInfo() {//沒有final可以被子類重寫
      String var1 = "this is animal!";
      boolean var2 = false;
      System.out.println(var1);
   }

   public Animal(@NotNull String color, int age) {
      Intrinsics.checkParameterIsNotNull(color, "color");
      super();
   }
}

7.2 可見性修飾符

在 Kotlin 中默認(rèn)修飾符與 Java 則不一樣,在 Kotlin 默認(rèn)是 public 而 Java 則默認(rèn)是 default (包級(jí)可見性)。此外 Kotlin 中還存在獨(dú)有的 internal 訪問可見修飾符。下面列出一張對(duì)應(yīng)表格

修飾符 表示含義 與 Java 比較
public Kotlin 默認(rèn)修飾符,全局可見 與 Java 中顯式指定的 public 效果一致
protected 受保護(hù)修飾符,類和子類可見 與 Java 一致,除了類和子類可見,其包內(nèi)也可見
private 私有修飾符,只有本類可見,類外文件內(nèi)可見 只能類內(nèi)可見
internal 模塊內(nèi)可見 無該修飾符

8. 總結(jié)

到這里有關(guān) Kotlin 中面向?qū)ο蟮牡谝徽揪徒Y(jié)束,回顧一下本篇文章主要介紹了 Kotlin 中類和對(duì)象定義和創(chuàng)建,以及類的構(gòu)造函數(shù)、init 初始化塊、可見性修飾符,并把這些特性語(yǔ)言一一和 Java 進(jìn)行對(duì)比,幫助快速掌握和理解。下篇文章將繼續(xù) Kotlin 面向?qū)ο蟮诙境橄蠛徒涌凇?/p>