《Kotlin入门实战》CH4 | 类与面向对象编程

类与面向对象编程

从面向过程到面向对象,再到设计模式,架构设计,面向服务,Sass、Pass和Iass等思想,各种软
件理论思想五花八门,但万变不离其宗:

你要解决一个什么样的问题?
你的问题是哪个领域的?
你的模型(数据结构)是什么?
你的算法是什么?
你对这个世界的本质认知是怎样的?
你的业务领域的逻辑问题、流程是什么?

声明类

1. 空类

2. 声明类和构造函数

class People(var id: Int) {
    var age: Int = 0;           // 没有延迟初始化的必须声明的时候初始化
    lateinit var name: String;  // 延迟初始化

    // 二级构造器必须调用主构造器
    // 构造器中参数不能使用val或者var声明
    constructor(id: Int, age: Int, name: String) : this(id) {
        this.age = age
        this.name = name
    }

    // 重写toString方法
    override fun toString(): String {
        return "People(id=$id, age=$age, name='$name')"
    }
}


fun main() {
    val people = People(42119999)   // 调用主构造器
    people.age = 20                 // 类中属性默认是public,在其他包中也可以访问
    people.name = "kris"
}

当子类继承了某个类之后,便可以使用父类中的成员变量,但并不是完全继承父类的所有成员变量。具体的原则如下:

  • 能够继承父类的public和protected成员变量;
  • 不能继承父类的private成员变量;
  • 对于父类的包访问权限成员变量,如果子类和父类在同一个包下,则子类能够继承;否则,子类不能继承;
  • 对于子类可以继承的父类成员变量,如果在子类中出现了同名称的成员变量,则会发生隐藏现象,即子类的成员变量会屏蔽掉父类的同名成员变量。如果要在子类中访问父类中的同名成员变量,需要使用super关键字进行引用。

3 Object对象

Kotlin中没有静态对象,需要实现单例模式,可以使用Object单例对象

object User{
    var id = "admin"
    var pw = "admin"

    override fun toString(): String {
        return "$id + $pw"
    }
}

fun main() {
    println(User) //  admin + admin
}

或者使用伴生对象

class DBClient(var id : Int){
    fun open(){
        println("DBClient id $id")
        openDB()
    }

    // 伴生对象,一个类只有一个
    companion object DBEngine{
        fun openDB(){
            println("DB engine open db")
        }
    }
}

fun main() {
    DBClient(1).open()
    DBClient(2).open()
}
/*
DBClient id 1
DB engine open db
DBClient id 2
DB engine open db
*/

4. 数据类

//主构造器不能为空
data class Music(var id : Int){
    lateinit var name : String;
}

这是Kotlin的数据类,可以反编译一下,查看对应的Java代码

public final class Music {
   @NotNull
   public String name; // 在类中声明的变量是public的
   private int id; // 主构造器中变量式私有的,也就是说不能继承
   
   // 构造器 
   public Music(int id) {
      this.id = id;
   }
    
// ============= get and set fun
   // get&set 都是被声明为final,不能重写
   @NotNull
   public final String getName() {
      String var10000 = this.name;
      if (var10000 == null) {
         Intrinsics.throwUninitializedPropertyAccessException("name");
      }

      return var10000;
   }

   public final void setName(@NotNull String var1) {
      Intrinsics.checkParameterIsNotNull(var1, "<set-?>");
      this.name = var1;
   }
    
   public final int getId() {
      return this.id;
   }

   public final void setId(int var1) {
      this.id = var1;
   }
//===============

   // component1 返回主构造器中下表为1的属性值
   public final int component1() {
      return this.id;
   }
   
   // 拷贝函数
   @NotNull
   public final Music copy(int id) {
      return new Music(id);
   }

   // $FF: synthetic method
   @NotNull
   public static Music copy$default(Music var0, int var1, int var2, Object var3) {
      if ((var2 & 1) != 0) {
         var1 = var0.id;
      }

      return var0.copy(var1);
   }
   // 只包含主构造器中的域
   @NotNull
   public String toString() {
      return "Music(id=" + this.id + ")";
   }
   // 只包含主构造器中的域
   public int hashCode() {
      return this.id;
   }
   // 只包含主构造器中的域
   public boolean equals(@Nullable Object var1) {
      if (this != var1) {
         if (var1 instanceof Music) {
            Music var2 = (Music)var1;
            if (this.id == var2.id) {
               return true;
            }
         }

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

  • 主构造函数至少包含一个参数;
  • 参数必须标识为val或者var;
  • 不能为abstract、open、sealed或者inner;
  • 不能继承其他类(但可以实现接口)。
  • 可以在解构声明中使用

Pair

Kotlin中提供了二元组Pair,和三元组Triple,可以使用Pair实现Map

public data class Pair<out A, out B>(
    public val first: A,
    public val second: B
) : Serializable {
    public override fun toString(): String = "($first, $second)"
}

/**
 * Creates a tuple of type [Pair] from this and [that].
 *
 * This can be useful for creating [Map] literals with less noise, for example:
 * @sample samples.collections.Maps.Instantiation.mapFromPairs
 */
public infix fun <A, B> A.to(that: B): Pair<A, B> = Pair(this, that)
// 重写了中缀表达式to

使用Pair实现Map

fun main() {
    val map = mapOf(1 to 'A', 2 to 'B', 3 to 'C')
    println(map) // 创建的是LinkedHashMap类型的Map
}

// mapOf方法在 kotlin.collections包中(默认导入)
public fun <K, V> mapOf(vararg pairs: Pair<K, V>): Map<K, V> =
    if (pairs.size > 0) pairs.toMap(LinkedHashMap(mapCapacity(pairs.size))) else emptyMap()

内部类

1.普通内部类

一个类可以嵌套其他类中,并且可以嵌套多层,普通内部类不持有外部类的引用,所以不能访问外部类属性。

class Out{
    var v = 1
    class inner{
        fun cout(){
            println(v) // Error
        }
    }
}

2.嵌套内部类

如果需要在内部类中获取外部类的this指针,可以使用嵌套内部类

class Out{
    var v = 1

    inner class inner{
        fun cout(){
            println(v) // OK
        }
    }
}

3.匿名内部类

匿名内部类也可以访问外部类属性。匿名内部类最经典的运用场景应该就是创建子线程

class MyThread {
    // 匿名内部类实现
    fun doRun1() {
        Thread(object : Runnable {
            override fun run() {
                println(Thread.currentThread().id)
            }
        }).start()
    }

    // Lambda表达式实现
    fun doRun2() {
        Thread(Runnable {
            println(Thread.currentThread().id)
        }).start()
    }

    //使用lambda表达式和匿名内部类
    fun doRun3() {
        val run = Runnable {
            println(Thread.currentThread().id)
        }
        Thread(run).start()
    }

    // 直接使用lambda表达式
    fun doRun4() {
        val run = {
            println(Thread.currentThread().id)
        }
        Thread(run).start()
    }

}


fun main() {
    println(Thread.currentThread().id)  // 1
    MyThread().doRun1()                 // 12
    MyThread().doRun2()                 // 13
    MyThread().doRun3()                 // 14
    MyThread().doRun4()                 // 15
}

方法4和方法2其实是一样的。方法1和方法3其实是一样的。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,468评论 5 473
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,620评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,427评论 0 334
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,160评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,197评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,334评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,775评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,444评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,628评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,459评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,508评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,210评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,767评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,850评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,076评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,627评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,196评论 2 341

推荐阅读更多精彩内容