阅读 85

Kotlin 进阶之路4 面向对象

1.面向对向编程

  • 本质上就是解决如何用程序描述世界的问题

  • 讨论如何把实际存在东西映射成程序的类和对象

  • 一种程序设计的思路、思想、方法


/**  * 面向对向编程  * 对某种事物进行抽象化,称之为建模  *  */ //kotlin 定义:class 类名 constructor(属性列表){更多的属性和方法描述} //构造器:用来设置类新实例的出厂配置 //类要被继承需要加open open class Chinese constructor(val sex: Boolean, var region: String) {     //普通属性,与变量定义相似     open val skin = "yellow"     //组合属性,由其它属性计算而来(get)     val avgLife: Double         get() {             when (this.region) {                     "Shanghai" -> {                 return 82.4             }                 "Beijing" ->{                     return 80.0                 }                 else -> {                     return 72.1                 }             }         }     //组合属性反过来可以影响其它属性(set,可选) this代表实例     var avgSalary : Int         get(){             when(this.region){                 "Shanghai" ->{ return 4000}                 "Beijing" ->{ return 5100}                 else ->{ return 3500}             }         }         set(value) {             when (value) {                 in 4500..Int.MAX_VALUE -> {                     this.region ="Beijing"                 }                 in 2800..4100->{                     this.region ="Shanghai"                 }                 else -> {                     this.region = "homeland"                 }             }         }     //方法:厨艺    open fun cook(): Unit {         val meau = arrayOf("宫爆鸡丁","番茄炒鸡蛋","葱爆牛肉")         val desc = meau.reduce{s1,s2->s1+","+s2}         println("我会${desc}")     } } class BeijingPeople(sex: Boolean, region: String = "Beijing") : Chinese(sex, region) {     val greatBuilding="the Forbidden City"     //override覆盖属性好方法     override val skin ="BeijingYellow"     override fun cook() {         super.cook()         val meau = arrayOf("北京烤鸭","北京炸酱面","北京包子")         val desc = meau.reduce{s1,s2->s1+","+s2}         println("我还会${desc}")     } } class ShanghaiPeople(sex: Boolean, region: String = "Shanghai") : Chinese(sex, region){     val greatBuilding="the Oriental Pearl Tower"     override val skin ="ShanghaiYellow"     override fun cook() {         super.cook()         val meau = arrayOf("大闸蟹","小汤包","芝士焗面")         val desc = meau.reduce{s1,s2->s1+","+s2}         println("我还会${desc}")     } } fun main(args: Array<String>) {     //实例化一个类     val Lili = BeijingPeople(true)     Lili.avgSalary = 6000     println(Lili.region)     println(Lili.avgSalary)     Lili.cook()     println()     val Jack = ShanghaiPeople(true)     Lili.avgSalary = 5000     println(Jack.region)     println(Jack.avgSalary)     Jack.cook() } 复制代码


Beijing 5100 我会宫爆鸡丁,番茄炒鸡蛋,葱爆牛肉 我还会北京烤鸭,北京炸酱面,北京包子 Shanghai 4000 我会宫爆鸡丁,番茄炒鸡蛋,葱爆牛肉 我还会大闸蟹,小汤包,芝士焗面 复制代码

2.抽象类和接口

抽象类:理解为半成品
接口:类似于协议或者某种成品就有的功能

接口
  • 不能有状态

  • 必须有类对其进行实现后实现

  • 接口,直观理解就是一种约定


   Kotlin的接口与Objective-C的Protocol比较类似 复制代码

  • 举例


interface InputDevice{ fun input(event: Any) } 复制代码

抽象类
  • 实现了一部分协议的半成品

  • 可以有状态,可以有方法实现

  • 必须由子类继承后使用

抽象类和接口的共性
  • 比较抽象,不能直接实例化

  • 有需要子类(实现类)实现的方法

  • 父类(接口)变量可以接受子类(实现类)的实例赋值

抽象类和接口的区别
  • 抽象类有状态,接口没有状态

  • 抽象类有实现方法,接口只能有无状态的默认实现

  • 抽象类只能单继承,接口可以多实现

  • 抽象类反应本质,接口提现能力


interface InputDevice {     fun input(event: Any) } interface USBInputDevice : InputDevice interface BLEInputDevice : InputDevice abstract  class USBMouse(val name:String) : USBInputDevice,OpticalMouse {     override fun input(event: Any) {     }     override fun toString(): String {         return name     } } interface OpticalMouse{ } class LogitechMouse:USBMouse("罗技鼠标"){ } class Computer {     fun addUSBInputDevice(inputDevice: USBInputDevice) {         //插入输入设备         println("add usb input device:$inputDevice")     }     fun addBLEInputDevice(inputDevice: BLEInputDevice) {         //插入输入设备         println("add input device:$inputDevice")     }     fun addInputDevice(inputDevice: InputDevice) {         when (inputDevice) {             is BLEInputDevice -> {                 addBLEInputDevice(inputDevice)             }             is USBInputDevice -> {                 addUSBInputDevice(inputDevice)             }             else -> {                 throw IllegalArgumentException("输入设备不支持")             }         }     } } fun main(args: Array<String>) {     val computer = Computer()     val mouse = LogitechMouse()     computer.addInputDevice(mouse) } 复制代码


add usb input device:罗技鼠标 复制代码

3.继承(实现)

继承(实现)语法要点
  • 父类需要open才可以被继承

  • 父类方法、需要open才可以被覆写

  • 接口、接口方法、抽象类默认为open

  • 覆写父类(接口)成员需要override关键字

  • class D:A(),B,C

  • 注意继承类时实际上调用了父类的构造方法

  • 类只能单继承,接口可以多实现

接口代理
  • class Manager(driver:Driver):Driver by driver

  • 接口方法实现交给代理类实现

接口方法冲突
  • 接口方法可以有默认实现

  • 签名一致且返回值有冲突

  • 子类(实现类)必须覆写冲突方法

  • super<[父类(接口)名]>.方法名


abstract class Person(open val age: Int) {     open fun work() {     } } class Coder(age: Int) : Person(age) {     override val age: Int         get() = 0     override fun work() {         super.work()         println("我是程序员")     } } class Doctor(override val age: Int) : Person(age) {     override fun work() {         super.work()         println("我是医生")     } } fun main(args: Array<String>) {     val person = Coder(28)     person.work()     println(person.age)     val person2 = Doctor(25)     person2.work()     println(person2.age) } 复制代码


我是程序员 0 我是医生 25 复制代码


class Manager : Driver, Writer {     override fun write() {     }     override fun drive() {     } } //写法一 //class SeniorManager(val driver: Driver,val writer: Writer):Driver,Writer{ //    override fun drive(){ //        driver.drive() //    } //    override fun write(){ //        writer.write() //    } //} //简写二 class SeniorManager(val driver: Driver, val writer: Writer) : Driver by driver, Writer by writer class CarDriver : Driver {     override fun drive() {         println("开车了")     } } class PPTWriter :Writer{     override fun write(){         println("做PPT了")     } } interface Driver {     fun drive() {     } } interface Writer {     fun write() {     } } fun main(args: Array<String>) {     val driver = CarDriver()     val writer = PPTWriter()     val seniorManager = SeniorManager(driver,writer)     seniorManager.drive()     seniorManager.write() } 复制代码


开车了 做PPT了 复制代码


interface InputDevice {     fun input(event: Any) } interface USBInputDevice : InputDevice interface BLEInputDevice : InputDevice abstract  class USBMouse(val name:String) : USBInputDevice,OpticalMouse {     override fun input(event: Any) {     }     override fun toString(): String {         return name     } } interface OpticalMouse{ } class LogitechMouse:USBMouse("罗技鼠标"){ } class Computer {     fun addUSBInputDevice(inputDevice: USBInputDevice) {         //插入输入设备         println("add usb input device:$inputDevice")     }     fun addBLEInputDevice(inputDevice: BLEInputDevice) {         //插入输入设备         println("add input device:$inputDevice")     }     fun addInputDevice(inputDevice: InputDevice) {         when (inputDevice) {             is BLEInputDevice -> {                 addBLEInputDevice(inputDevice)             }             is USBInputDevice -> {                 addUSBInputDevice(inputDevice)             }             else -> {                 throw IllegalArgumentException("输入设备不支持")             }         }     } } fun main(args: Array<String>) {     val computer = Computer()     val mouse = LogitechMouse()     computer.addInputDevice(mouse) } 复制代码


add usb input device:罗技鼠标 复制代码

4.Kotlin和Java可见性对比

KotlinJava
publicpublic
privatepriavte
protectedprotected
-default(包内可见)
internal(模块类可见)-

5.对象声明和表达式

object
  • 只有一个实例的类

  • 不能自定义构造方法

  • 可以实现接口、继承父类

  • 本质上就是单例模式最基本的实现


/**  * 有时候只要对某各类进行改造,供零时使用,避免继承  * 对象声明和表达式就很有作用  *  * 面向对象编程的优化,避免一些继承导致的代价过高,保持代码的整洁  */ //对中国人来说,这个类,可能各省人适合继承 open class Chinese(var name: String) {     open val skin = "yellow" } fun main(args: Array<String>) {     //但如果外国人入籍,就不适合用继承     //对象表达式:val 对象名 = object : 类,接口 {//属性或方法的override定义}     val Jack= object : Chinese ("Jack Marry")     {         override val skin = "white"     }     println(Jack.skin)     //纯对象表达式:临时使用,无须继承任何类     val loc = object {         var x = 100         var y = 200     }     println(loc.x)     //相当于调用函数     NetworkRequestManager.register()     //半生对象的方法,与类关联性强     IDCard.create() } //对象声明,不能用在函数中     //一般用于对其他类使用上的包装 object NetworkRequestManager{     fun register(){         println("连接网络注册中...")     } } //半生对象:一般用于创建一个类的实例"工厂"方法 //Java中的 静态成员 class IDCard{     companion object {         fun create() = IDCard()     } } 复制代码


white 100 连接网络注册中... 复制代码

6.半生对象与静态成员

  • 每个类可以对应一个伴生对象

  • 伴生对象的成员全局独一份

  • 伴生对象的成员类似Java的静态成员

  • 静态成员考虑用包级函数、变量替代

  • JvmField和JvmStatic的使用


fun main(args: Array<String>) {     val a = minOf(args[0].toInt(), args[1].toInt())     val latitude = Latitude.ofDouble(3.0)     val latitude2 = Latitude.ofLatitude(latitude)     println(Latitude.TAG) } class Latitude private constructor(val value: Double) {     companion object {         @JvmStatic         fun ofDouble(double: Double): Latitude {             return Latitude(double)         }         fun ofLatitude(latitude: Latitude): Latitude {             return Latitude(latitude.value)         }         @JvmField         val TAG:String = "Latitude"     } } 复制代码


Latitude 复制代码

JvmStatic JvmField 用于Java类调用


public class StaticJava {     public static void main(String[] args){         Latitude latitude = Latitude.ofDouble(4);         System.out.println("Java:"+Latitude.TAG);     } } 复制代码


Java:Latitude 复制代码

6.方法重载Overloads 和默认参数

方法重载Overloads
  • 名称相同、参数不同的方法

  • Jvm函数签名的概念:函数名、参数列表

  • 跟返回值没有关系

默认参数
  • 为函数参数设定一个默认值

  • 可以为任意位置的参数设置默认值

  • 函数调用产生混淆时用具名参数

两者关系
  • 避免定义关系不大的重载

  • 方法重载最好能转化为默认参数

  • 不好的设计:


- List.remove(int) - List.remove(Object) 复制代码


//方法重载和函数名有和参数列表有关系,和函数返回值没关系 class Overloads {     //    fun a(): Int { //        return 0 //    }     @JvmOverloads //默认参数 是给java调用的     fun a(int: Int = 0): Int {         return int     } } fun main(args: Array<String>) {     val overloads = Overloads()     overloads.a()     val integerList = ArrayList<Int>()     integerList.add(555)     integerList.add(2)     integerList.add(3)     integerList.add(4)     integerList.add(9)     integerList.add(45)     println(integerList.toString())     integerList.removeAt(1)     integerList.remove(9)     println(integerList.toString()) } 复制代码


[555, 2, 3, 4, 9, 45] [555, 3, 4, 45] 复制代码

7.扩展成员

  • Java调用扩展成员类似调用静态方法

  • 为现有类添加方法、属性


- fun X.y():Z{...} - val X.m 主义扩展属性不能初始化,类似接口属性 复制代码


fun main(args: Array<String>) {     println("abc" * 16)     "abc".b = 5     println("abc".b) } operator fun String.times(int: Int): String {     val stringBuilder = StringBuilder()     for (i in 0 until int) {         stringBuilder.append(this)     }     return stringBuilder.toString() } val String.a: String     get() = "abc" var String.b: Int     set(value) {     }     get() = 5 复制代码


abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc 5 复制代码

8.属性代理

  • 定义方法:


- val/var <property name>:<Type> by   <expression> 复制代码

  • 代理者需要实现相应的setValue/getValue方法:

  • lazy原理剖析

9.数据类

  • 再见,JavaBean

  • 默认实现的copy,toString等方法

  • componentN方法

  • allOpen和noArg插件 在编译器 把final关键字去掉


import com.haocai.kotlindemo.annotations.Poko @Poko data class Country(val id: Int, val name: String) class ComponentX {     operator fun component1(): String {         return "您还,我是"     }     operator fun component2(): Int {         return 1     }     operator fun component3(): Int {         return 1     }     operator fun component4(): Int {         return 0     } } fun main(args: Array<String>) {     val china = Country(0, "中国")     println(china)     println(china.component1())     println(china.component2())     val (id, name) = china     println(id)     println(name) //    for ((index, value) in args.withIndex()) { //        println(index) //        println(value) //    }     val componentX = ComponentX()     val (a, b, c, d) = componentX     println("$a $b $c $d") } 复制代码

10.内部类

  • 定义在类内部的类

  • 与类成员有相似的访问控制

  • 默认是静态内部类,非静态用inner关键字

  • this@Outter,this@Inner的用法

  • 没有定义名字的内部类

  • 类名编译时生成,类似Outter$1.class

  • 可继承父类、实现多个接口,与Java注意区别

Kotlin写法:

open class Outter {     val a: Int = 0     inner class Inner {         val a: Int = 5         fun hello() {             println(this@Outter.a)         }     } } interface OnClickListener {     fun onClick() } class View {     var onClickListener: OnClickListener? = null } fun main(args: Array<String>) {     val inner = Outter().Inner()     inner.hello()     val view = View()     //匿名内部类 即可以实现接口,同时继承外部类(如,Outter())     view.onClickListener = object : Outter(),OnClickListener{         override fun onClick() {         }     } } 复制代码


0 复制代码

Java类似写法:

public class InnerClassJava {     private int a;     public static void main(String... args) {         InnerClassJava innerClassJava = new InnerClassJava();         Inner inner = innerClassJava.new Inner();         //Inner inner = new Inner(); 报错 除非Inner 是静态         inner.hello();         View view = new View();         view.setOnClickListener(new OnClickListener() {             @Override             public void onClick() {             }         });     }     public class Inner {         public void hello() {             System.out.println(InnerClassJava.this.a); //非静态内部类可以持有外部类的状态         }     } } 复制代码


0 复制代码

11.枚举

  • 实例可数的参数,注意枚举也是类

  • 可以修改构造,添加成员

  • 可以提升代码的表现力,也有一定的性能开销


enum class LogLevel(val id: Int) {     VERBOSE(0), DEBUG(1), INFO(2), WARN(3), ERROR(4), ASSERT(5);     fun getTag(): String {         return "$id,$name"     }     override fun toString(): String {         return "$name,$ordinal"     } } class LogLevel2 protected constructor() {     companion object {         val VERBOSE = LogLevel2()         val DEBUG = LogLevel2         val INFO = LogLevel2         val WARN = LogLevel2         val ERROR = LogLevel2         val ASSERT = LogLevel2     } } fun main(args: Array<String>) {     println(LogLevel.INFO.getTag())     println(LogLevel.DEBUG.ordinal)     LogLevel.values().map(::println) } 复制代码


2,INFO 1 VERBOSE,0 DEBUG,1 INFO,2 WARN,3 ERROR,4 ASSERT,5 复制代码

12.密封类

  • 子类可数(从v1.1开始,只需要与密封类在同一个文件中)

  • 枚举是实例可数


sealed class PlayerCmd{     class Play(val url:String ,val position:Long = 0):PlayerCmd()     class Seek(val position:Long ):PlayerCmd()     object Pause:PlayerCmd()     object Resume:PlayerCmd()     object Stop:PlayerCmd() } enum class PlayerState{     IDLE,PAUSE,PLAYING }


作者:冬日毛毛雨
链接:https://juejin.cn/post/7025867496448081927


文章分类
后端
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐