Kotlin学习5

作者: flynnny | 来源:发表于2021-05-19 02:38 被阅读0次

    继承与重载的open关键字

    类默认都是封闭(final)的,要让某个类开放继承,必须使用open关键字修饰他

    open class Product(val name:String){
      fun des() = "Product: $name"
      //父类的函数也要以open关键字修饰,子类才能覆盖它
      open fun load() ="nothing..."
    }
    class LuxProduct :Product("Luxury"){
      override fun load() = "luxProduct loading..."//父类方法没用open会报错
    }
    
    fun main(){
      val p :Product = LuxuryProduct()
      println(p.load()) 
    }
    

    类型转换(as关键字)

    kotlin的is关键字用来检测某个对象的类型

    open class Product(val name:String){
      fun des() = "Product: $name"
      //父类的函数也要以open关键字修饰,子类才能覆盖它
      open fun load() ="nothing..."
    }
    class LuxProduct :Product("Luxury"){
      override fun load() = "luxProduct loading..."//父类方法没用open会报错
    
      fun special() = "LuxProduct  special"
    }
    
    
    fun main(){
      val p= LuxuryProduct()
      println(p is LuxuryProduct) //true
      println(p is Product) //true
    
    //as 关键字
      if(p is LuxuryProduct){
        println((p as LuxuryProduct).special())
      }
    }
    

    智能类型转换

    kotlin编译器,只要确定any is 父类条件检查属实,他就会将any当做子类类型对待,因此允许你不经类型转换直接使用

    println((p as LuxuryProduct).special())//转一次就不需要再转了
    println(p.special())
    

    Any超类

    kotlin共同继承一个Any超类,java里的Object类

    println(p is Any) //true
    

    object关键字

    使用object关键字,可以定义一个只能产生一个实例的类--单例
    使用object关键字有三种方式
    对象声明
    对象表达式
    伴生对象

    对象声明

    对象声明有利于组织代码和管理状态,尤其是管理整个应用运行生命周期内的某些一致性状态

    object ApplicationConfig{
      init{
        println("loading config ...")
      }
      fun setSomething(){
        println("setSongthing")
      }
    }
    fun main(){
      //ApplicationConfig即是类名又是实例名字
      ApplicationConfig.setSomething()
      pringln(ApplicationConfig)
      pringln(ApplicationConfig)
    }
    

    对象表达式

    有时候不一定非要定义一个新的命名类不可,也许你需要某个现有类的一种变体实例,但只需要一次就行了,事实上,对于这种用完就丢的类实例,连命名都可以省了。这个对象表达式是xx的子类,这个匿名类依然遵循object关键字的一个规则,即一旦实例化,该匿名类只能有唯一一个实例存在

    open class Player{
      open fun load() = "loading nothing."
    }
    fun main(){
      val p = object:Player(){
        override fun load()="anonymous class load..."
      }
      println (p.load())
    }
    

    伴生对象

    如果你想将某个对象的初始化和一个类实例捆绑在一起,可以考虑使用伴生对象,使用companion修饰符,你可以在一个类定义里声明一个伴生对象,一个类只能有一个伴生对象。

    import java.io.File
    
    open class ConfigMap{
      //只有初始化ConfigMap类或调用load函数时,伴生对象的内容才会载入
      //而且无论实例化多少次,这个伴生对象只能有一个实例存在
      companion object{
        private const val PATH = "xxx"
        fun load() =FIle(PATH).readBytes()
      }
    }
    fun main(){
      //static
      ConfigMap.load()
    }
    

    嵌套类

    一个类只对另一个类有用,那么将其嵌入到该类中并使这两个类保持在一起。

    class Player2(){
      class Equipment(var name:String){
        fun show() = printin("$name")
      }
    }
    fun main(){
      //这里Player2.Equipment()就可以了
      Player2.Equipment("AK47").show()
    }
    

    数据类

    专门设计用来存储数据的类
    数据类型提供了toString的个性化实现
    ==符号默认是比较引用值,数据类型提供了equals和hashCode的个性化实现

    data class Coordinate(var x:Int,var y:Int){
      val isInBounds = x>=0 && y>=0
    }
    fun main (){
      println(Coordinate(1,5)) //Coordinate(x=1,y=5)
      //==比较的是内容,equals 默认是===
      //===比较的是引用
      println(Coordinate(1,5)==Coordinate(1,5))//true 如果Coordinate类不加data是false
      
    }
    

    copy函数

    方便的复制一个对象。

    data class Student(var name:String ,val age :Int){
      var score = 10;
      private val hobby = "music"
      val subject :String
      init{
        println("init student")
        subject = "math"
      }
      constructor(_name:String):this(_name,10){
        score = 20
      }
      override fun toString ():String{
        return "Student(name='$name', age = $age,"+
                    "score=$score, hobby=' $hobby',"+
                    "subject='$subject')"
      }
    }
    fun main(args:Array<String>){
      val s = Student("jack")
      val copy = s.copy("Rose")
      println(copy)//Student(name = 'Rose',age = 10,...)
    }
    

    copy函数有个小坑:次构造函数里如果对某个属性作了更改,新的copy对象是没有改的!!!!

    解构声明

    解构声明的后台实现就是声明component1、component2等若干个组件函数,让每个函数负责管理你想反回的一个属性数据,如果你定义一个数据类,他会自动为所有定义在主构造函数的属性添加对应的组建函数

    class PlayerScore(val exp:Int , val level:Int){
      //固定是component1和component2
      operator fun component1() = exp
      operator fun component2() = level
    }
    
    fun main(){
      val (x,y) = PlayerScore(10,20)
    }
    

    数据类直接支持解构语法

    运算符重载

    13.png
    data class Coordinate2(var x:Int,var y :Int){
      val isInBounds = x>=0&&y>=0
    
      operator fun plus(other:Coordinate2)=
            Coordinate2(x +other.x,y+other.y)
    }
    fun main(){
      val c1 = Coordinate2(5,6)
      val c2 = Coordinate2(10,20)
      println(c1+c2)
    }
    

    枚举类

    enum class Dir{
      EAST,
      WEST,
      SOUTH,
      NORTH
    }
    fun main(){
      println(Dir.EAST)//EAST
    }
    

    枚举类定义函数

    //给枚举类添加一个柱构造函数
    enum class Dir2(private val coordinate:Coordinate){
      //因为枚举类的构造函数都带参数,所以定义每个枚举类常量时
      //都要传入Coordinate对象,调用构造函数
      EAST(Coordinate(5,-1)),
      WEST(Coordinate(1,0)),
      SOUTH(Coordinate(0,1)),
      NORTH(Coordinate(-1,0));
      
      fun updateCoordinate(playerC:Coordinate) =
        Coordinate(playerC.x+coordinate.x,
                          playerC.y+coordinate.y)
    }
    fun main(){
      pringln(DIr2.EAST.updateCoordinate(Coordinate(10,20)))
    }
    

    代数数据类型

    可以用来标识一组子类型的闭集,枚举类就是一种简单的ADT

    enum class Liscen{
      UNQUALIFIED,
      LEARNING,
      QUALIFIED;
    }
    class Drive(var status :Liscen){
      fun check() :String{
        //不使用else,且编译器会帮你检查遗漏
        return when (status){
          Liscen.UNQUALIFIED->"没资格"
          Liscen.LEARNING->"在学"
          Liscen.QUALIFIED->"有资格"
        }
      }
    }
    

    密封类(sealed class)

    密封类实现更复杂的ADT。
    密封类可以有若干个子类,要继承密封类,这些子类必须和他定义在同一个文件里

    sealed class Lic2{
      object UnQualified :Lic2()
      object Learning:Lic2()
      class Qualified(val licenseId:String):Lic2()
    }
    class Drive2(var status:Lic2){
      fun check():String{
        return when(status){
          is Lic2.UnQualified ->"没资格"
          is Lic2.Learning ->"在学"
          is Lic2.Qualified ->"有资格,编号:"+
              "${(this.status as Lic2.Qualified).licenseId}"
        }
      }
    }
    fun main(){
      val status = Lic2.Learning
      val driver = Driver2(status)
      println(driver.check())
    
      val status2 = Lic2.Qualified("12312") 
      val driver2 = Driver2(status)
      println(driver2.check())
    }
    

    使用数据类条件

    14.png

    小结

    相关文章

      网友评论

        本文标题:Kotlin学习5

        本文链接:https://www.haomeiwen.com/subject/tcsujltx.html