久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Kotlin學(xué)習(xí)手記——單例、內(nèi)部類、數(shù)據(jù)類,、枚舉類、密封類,、內(nèi)聯(lián)類

 印度阿三17 2020-12-24

Kotlin單例:

只需要類前面添加object關(guān)鍵字即可,,object定義類等價(jià)于java的惡漢式的單例模式

object Singleton {
    var x: Int = 2 
    fun y(){ }

    init {
        //object不能定義構(gòu)造函數(shù),但可以定義init塊
    }
}

object不能定義構(gòu)造函數(shù),,但可以定義init

使用:

fun main() {
    Singleton.x
    Singleton.y()
}

@JvmStatic@JvmField

object Singleton {
    @JvmField var x: Int = 2 //生成java的靜態(tài)成員 不會(huì)生成getter和setter方法
    @JvmStatic fun y(){ } //生成java的靜態(tài)方法
}

在這里插入圖片描述
在這里插入圖片描述
普通kotlin類(非單例)中使用使用JvmFieldJvmStatic

class Foo {
    //普通類中使用JvmField和JvmStatic
    companion object {
        @JvmField var x: Int = 2
        @JvmStatic fun y(){  }
    }
}

注意,,加的注解@JvmField@JvmStatic只針對(duì)java平臺(tái)的可用,,其他平臺(tái)并不可行。

單例的object類仍可以繼承類:

object Singleton: Runnable{
    override fun run() {

    }
}

內(nèi)部類:
在這里插入圖片描述

在kotlin中類內(nèi)部的class前面不寫修飾符默認(rèn)就是靜態(tài)內(nèi)部類,,class前面寫 inner修飾符才是java中的普通內(nèi)部類,,與java一樣,普通內(nèi)部類會(huì)持有外部類的對(duì)象引用,。

class Outer {
    //普通內(nèi)部類 與java一樣會(huì)持有外部類的引用
    inner class Inner
    //默認(rèn)靜態(tài)內(nèi)部類
    class StaticInner
}
fun main() {
    val inner = Outer().Inner()
    val staticInner = Outer.StaticInner()
}

object類內(nèi)部的object類默認(rèn)是靜態(tài)的 不存在非靜態(tài)的情況 不能定義成inner

object OuterObject {
    //內(nèi)部object默認(rèn)是靜態(tài)的 不存在非靜態(tài)的情況 不能定義成inner
    object StaticInnerObject
}

匿名內(nèi)部類:

fun main() {
    //匿名內(nèi)部類
    object : Cloneable {

    }
}

其實(shí)就是object 省略類名直接實(shí)現(xiàn)接口,。

匿名內(nèi)部類 可用繼承多個(gè)接口,java不行:

fun main() {

    // 類型是混合類型:Cloneable & Runnable 
    val runnableCloneable = object : Cloneable, Runnable {
        override fun run() {

        }
    }
 
}

實(shí)現(xiàn)多個(gè)接口時(shí),,它的類型是多個(gè)接口類型的混合類型,。

Local class :

fun main() {
//本地函數(shù)
    fun localFunc(){
        println("Hello")
    }

    //對(duì)應(yīng)Java的local class
    class LocalClass:  Cloneable, Runnable{
        override fun run() {}
    }
}

可以對(duì)比java的local class實(shí)現(xiàn),其實(shí)就是在靜態(tài)函數(shù)的內(nèi)部定義一個(gè)類:

public class JavaInnerClasses {
    public static void main(String... args) {
        class LocalClass implements Cloneable, Runnable {
            @Override
            public void run() { }
        }
    }
}

說實(shí)話,,寫了這么多年代碼,,未曾這么干過。,。

數(shù)據(jù)類:

kotlin中提供一個(gè)data關(guān)鍵字,,data修飾的類就是一個(gè)數(shù)據(jù)類,對(duì)標(biāo)java的bean類:


data class Book(val id: Long, val name: String, val author: Person)

data class Person(val id: Long, val name: String, val age: Int)

與java的bean類相比,,kotlin的data類不能被繼承,,并且屬性要全部寫到構(gòu)造函數(shù)當(dāng)中,沒有無參的構(gòu)造函數(shù),。確實(shí)簡(jiǎn)便了許多,!

在這里插入圖片描述
并且編譯器會(huì)為data類生成了一些好用的方法:

    val book = Book(0, "Kotlin in Action", Person(1, "Dmitry", 40))
    //編譯器生成的方法 copy component1
    book.copy()
    val id = book.component1()
    val name = book.component2()
    val author = book.component3()

其中copy()component1()等都是編譯器自動(dòng)生成的,component方法的意義是方便解構(gòu)賦值的使用:

    //解構(gòu)賦值,,對(duì)應(yīng)的字段是通過component方法獲取的
    val (id, name, author) = book

關(guān)于解構(gòu):

     //解構(gòu)
    val pair = "Hello" to "World"
    val (hello, world) = pair

data不能被繼承,,那么為啥不能有子類呢?

可以先看一下kotlin為data類生成的對(duì)應(yīng)的java類是什么樣的,,查看方式,,doule shift鍵,然后Actions中輸入kotlin Bytecode顯示:
在這里插入圖片描述
點(diǎn)擊Decompile即可查看對(duì)應(yīng)生成的java代碼
在這里插入圖片描述
以下是Book的數(shù)據(jù)類對(duì)應(yīng)生成的java代碼

public final class Book {
   private final long id;
   @NotNull
   private final String name;
   @NotNull
   private final Person author;

   public final long getId() {
      return this.id;
   }

   @NotNull
   public final String getName() {
      return this.name;
   }

   @NotNull
   public final Person getAuthor() {
      return this.author;
   }

   public Book(long id, @NotNull String name, @NotNull Person author) {
      Intrinsics.checkNotNullParameter(name, "name");
      Intrinsics.checkNotNullParameter(author, "author");
      super();
      this.id = id;
      this.name = name;
      this.author = author;
   }

   public final long component1() {
      return this.id;
   }

   @NotNull
   public final String component2() {
      return this.name;
   }

   @NotNull
   public final Person component3() {
      return this.author;
   }

   @NotNull
   public final Book copy(long id, @NotNull String name, @NotNull Person author) {
      Intrinsics.checkNotNullParameter(name, "name");
      Intrinsics.checkNotNullParameter(author, "author");
      return new Book(id, name, author);
   }

   // $FF: synthetic method
   public static Book copy$default(Book var0, long var1, String var3, Person var4, int var5, Object var6) {
      if ((var5 & 1) != 0) {
         var1 = var0.id;
      }

      if ((var5 & 2) != 0) {
         var3 = var0.name;
      }

      if ((var5 & 4) != 0) {
         var4 = var0.author;
      }

      return var0.copy(var1, var3, var4);
   }

   @NotNull
   public String toString() {
      return "Book(id="   this.id   ", name="   this.name   ", author="   this.author   ")";
   }

   public int hashCode() {
      long var10000 = this.id;
      int var1 = (int)(var10000 ^ var10000 >>> 32) * 31;
      String var10001 = this.name;
      var1 = (var1   (var10001 != null ? var10001.hashCode() : 0)) * 31;
      Person var2 = this.author;
      return var1   (var2 != null ? var2.hashCode() : 0);
   }

   public boolean equals(@Nullable Object var1) {
      if (this != var1) {
         if (var1 instanceof Book) {
            Book var2 = (Book)var1;
            if (this.id == var2.id && Intrinsics.areEqual(this.name, var2.name) && Intrinsics.areEqual(this.author, var2.author)) {
               return true;
            }
         }

         return false;
      } else {
         return true;
      }
   }
}

除了類名方法名前面添加了final關(guān)鍵字以外,,生成了許多方法,,其中有重寫hashCode()equals()方法,所以如果有一個(gè)類繼承了data類,,可能導(dǎo)致屬性變化,,從而導(dǎo)致hashCode()equals()方法的結(jié)果不一致。
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
data類的屬性最好全部為基本類型或者其他data類型,,保持它的純凈性,。

另外,有方法可以破除data類的不可繼承性,也有網(wǎng)友在吐槽kotlin的這個(gè)設(shè)計(jì),,覺得它不好,,其實(shí)如果你想用一個(gè)可以繼承到類,只需要把data關(guān)鍵字去掉,,建一個(gè)普通類就好了。kotlin這樣設(shè)計(jì)肯定是想保持它的純潔性,,如果可繼承,,只會(huì)變的更復(fù)雜。

破除data類的不可繼承性需要額外添加兩個(gè)插件:

plugins {
...
    id 'org.jetbrains.kotlin.plugin.noarg' version '1.4.20'
    id 'org.jetbrains.kotlin.plugin.allopen' version '1.4.20'
}

noArg {
    invokeInitializers = true
    annotations "com.bennyhuo.kotlin.advancedtypes.dataclasses.PoKo"
}

allOpen {
    annotations "com.bennyhuo.kotlin.advancedtypes.dataclasses.PoKo"
}

上面是參考學(xué)習(xí)資料當(dāng)中的代碼工程中的配置,,然后在data類上加注解即可

@PoKo
data class Book(val id: Long, val name: String, val author: Person)

這時(shí)同樣去查看Book的數(shù)據(jù)類對(duì)應(yīng)生成的java代碼會(huì)發(fā)現(xiàn),,之前的類名和get方法名前面的final關(guān)鍵字被移除了,也就是可以被繼承使用了,,同時(shí)會(huì)生成一個(gè)無參的構(gòu)造函數(shù),。可見比較麻煩,,非有必要,,還是不要這么干。,。

枚舉類:

kotlin里面的枚舉類跟java差不多

enum class State {
    Idle, Busy
}

//枚舉定義構(gòu)造函數(shù) 同java
enum class State1(val id: Int) {
    Idle(0), Busy(1)
}

enum class Color {
    White, Red, Green, Blue, Yellow, Black
}
fun main() {
    State.Idle.name // Idle
    State.Idle.ordinal // 0

    val state = State.Idle
    //枚舉全部值
    val value = when (state) {
        State.Idle -> { 0 }
        State.Busy -> { 1 }
    }
    //枚舉創(chuàng)建區(qū)間
    val colorRange = Color.White .. Color.Green
    val color = Color.Blue //Blue不在區(qū)間內(nèi)
    println(color in colorRange)
}

枚舉類不可繼承其他類,,因?yàn)槊杜e類有父類是enum,但是可以實(shí)現(xiàn)接口:

enum class State: Runnable{
    Idle, Busy{
        override fun run() {
            println("For Busy State.")
        }
    };

    override fun run() {
        println("For  Every State.")
    }
}
fun main() {
    State.Idle.run()
    State.Busy.run()
}

枚舉類可以定義擴(kuò)展函數(shù):

fun State.successor(): State? {
    return State.values().let {
        if (ordinal   1 >= it.size) null
        else it[ordinal   1]
    }
}

fun State.predecessor(): State? {
    return State.values().let {
        if (ordinal - 1 < 0) null
        else it[ordinal - 1]
    }
}
fun main() {
    println(State.Idle.successor())
    println(State.Busy.successor())
}

密封類:
在這里插入圖片描述
其實(shí)就是一個(gè)只能在同一個(gè)文件中定義子類的抽象類,。不得不說kotlin玩的花樣很多,,會(huì)玩。,。,。

定義方式是在類的前面加sealed關(guān)鍵字

sealed class PlayerState

object Idle : PlayerState()

class Playing(val song: Song) : PlayerState() {
    fun start() {}
    fun stop() {}
}

class Error(val errorInfo: ErrorInfo) : PlayerState() {
    fun recover() {}
}

完整的示例:控制播放器播放狀態(tài)的例子

data class Song(val name: String, val url: String, var position: Int)
data class ErrorInfo(val code: Int, val message: String)

object Songs {
    val StarSky = Song("Star Sky", "https:///321144.mp3", 0)
}

sealed class PlayerState

object Idle : PlayerState()

class Playing(val song: Song) : PlayerState() {
    fun start() {}
    fun stop() {}
}

class Error(val errorInfo: ErrorInfo) : PlayerState() {
    fun recover() {}
}

class Player {
    var state: PlayerState = Idle

    fun play(song: Song) {
        this.state = when (val state = this.state) {
            Idle -> {
                Playing(song).also(Playing::start)
            }
            is Playing -> {
                state.stop()
                Playing(song).also(Playing::start)
            }
            is Error -> {
                state.recover()
                Playing(song).also(Playing::start)
            }
        }
    }
}

fun main() {
    val player = Player()
    player.play(Songs.StarSky)
}

注意其中的when表達(dá)式的使用,可見它可以用來替代枚舉類做類似的功能,,子類的個(gè)數(shù)也是全部可枚舉的,。跟枚舉類有相似之處。
在這里插入圖片描述
內(nèi)聯(lián)類:
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
簡(jiǎn)而言之,,內(nèi)聯(lián)類是一種類型的包裝類,,類前面加inline關(guān)鍵字,構(gòu)造器只能有一個(gè)參數(shù),,不能繼承類,,不能被繼承,不能作為內(nèi)部類,。類似于java的Integer,、Double這種吧,但有不同,。

內(nèi)聯(lián)類雖然不能繼承類或被繼承,,但是可以實(shí)現(xiàn)接口,。

//
//只能有方法不能有屬性
inline class BoxInt(val value: Int): Comparable<Int> {
    override fun compareTo(other: Int)
            = value.compareTo(other)

    operator fun inc(): BoxInt {
        return BoxInt(value   1)
    }
}

BoxInt會(huì)做編譯優(yōu)化,只有在需要的時(shí)候才使用包裝類 多數(shù)情況下直接使用Int,,可以反編譯字節(jié)碼生成的java代碼查看,。另外,還有個(gè)特點(diǎn)就是它只能有方法不能有屬性,。

內(nèi)聯(lián)類也可以用來模擬枚舉類,,與枚舉相比內(nèi)存占用小,但使用方式類似

inline class State(val ordinal: Int) {
    companion object {
        val Idle = State(0)
        val Busy = State(1)
    }

    fun values() = arrayOf(Idle, Busy)

    val name: String
        get() = when (this) {
            State.Idle -> "Idle"
            State.Busy -> "Busy"
            else -> throw  IllegalArgumentException()
        }
}

inline class Color(val value: UInt) {
    companion object {
        val Red = Color(0xFFFF0000u)
        val Green = Color(0xFF00FF00u)
        val Blue = Color(0xFF0000FFu)
    }

    fun values() = arrayOf(Red, Green, Blue)

    val name: String
        get() = when (this) {
            Red -> "Red"
            Green -> "Green"
            Blue -> "Blue"
            else -> throw  IllegalArgumentException()
        }
}

fun main() {
    State.Busy
    Color.Blue

    var boxInt = BoxInt(5)
    if(boxInt < 10){
        println("value is less than 10")
    }

    val newValue = boxInt.value * 200
    println(newValue)
    boxInt  
    println(boxInt)
}

在這里插入圖片描述
密封類的實(shí)例:遞歸整型列表的簡(jiǎn)單實(shí)現(xiàn)

sealed class IntList {
    object Nil: IntList() {
        override fun toString(): String {
            return "Nil"
        }
    }

    data class Cons(val head: Int, val tail: IntList): IntList(){
        override fun toString(): String {
            return "$head, $tail"
        }
    }

    fun joinToString(sep: Char = ','): String {
        return when(this){
            Nil -> "Nil"
            is Cons -> {
                "${head}$sep${tail.joinToString(sep)}"
            }
        }
    }
}

fun IntList.sum(): Int {
    return when(this){
        IntList.Nil -> 0
        is IntList.Cons -> head   tail.sum()
    }
}

operator fun IntList.component1(): Int? {
    return when(this){
        IntList.Nil -> null
        is IntList.Cons -> head
    }
}

operator fun IntList.component2(): Int? {
    return when(this){
        IntList.Nil -> null
        is IntList.Cons -> tail.component1()
    }
}

operator fun IntList.component3(): Int? {
    return when(this){
        IntList.Nil -> null
        is IntList.Cons -> tail.component2()
    }
}

fun intListOf(vararg ints: Int): IntList {
    return when(ints.size){
        0 -> IntList.Nil
        else -> {
            IntList.Cons(
                ints[0],
                //array前面加* 展開數(shù)組
                intListOf(*(ints.slice(1 until ints.size).toIntArray()))
            )
        }
    }
}

// [0, 1, 2, 3]
fun main() {
    //val list = IntList.Cons(0, IntList.Cons(1,  IntList.Cons(2,  IntList.Cons(3, IntList.Nil))))
    val list = intListOf(0, 1, 2, 3)
    println(list)
    println(list.joinToString('-'))
    println(list.sum())

    val (first, second, third) = list

    println(first)
    println(second)
    println(third)

    //val (a, b, c, d, e) = listOf<Int>()
}
來源:https://www./content-4-797401.html

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購(gòu)買等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多