美文网首页
Kotlin基础(二)——面向对象

Kotlin基础(二)——面向对象

作者: 紫依卓兰 | 来源:发表于2018-11-12 17:13 被阅读15次

    抽象类和接口

    接口

    • 直观理解就是一种约定,Kotlin的接口与Objective-c的Proticol比较类似
    • 不能有状态
    • 必须由类对其进行实现后使用

    抽象类

    • 实现了一部分协议的半成品
    • 可以有状态,可以有方法实现
    • 必须有子类集成后使用

    抽象类和接口的共性

    • 比较抽象,不能直接示例化
    • 有需要子类(实现类)实现的方法
    • 父类(接口)变量可以接受子类(实现类)的示例赋值

    抽象类和接口的区别

    • 抽象类有状态,接口没有状态
    • 抽象类有方法实现,接口只能有无状态的默认实现
    • 抽象类只能单继承,接口I可以多实现
    • 抽象类反映本质,接口体现能力

    继承(实现)语法要点

    • 父类需要open才可以被继承(抽象类不需要,生来就是被继承的)
    • 父类方法、属性需要open才可以被复写
    • 接口、接口方法、抽象类默认为open
    • 覆写父类(接口)成员需要override关键字
    • class D:A(),B,C
    • 注意继承类时实际上是调用了父类构造方法
    • 类只能但继承,接口可以多实现

    接口代理

    • 接口方法实现交给代理类实现
    interface Driver{
        fun drive()
        fun abc()
    }
    
    class Manager(driver:Driver):Driver by driver
    
    
    class Manager(driver: Driver):Driver{
        override fun drive(){
            driver.drive()
        }
        override fun abc(){
            driver.abc()
        }
    }
    

    接口方法冲突

    • 接口方法可以有默认实现
    • 签名一致且返回值相同的冲突
    • 子类(实现类)必须覆写冲突方法
    • super<父类(接口)名>.方法名(参数列表)

    类成员的可见性对比

    Kotlin Java
    private private
    protected protected
    - default(包内可见)
    internal(模块内可见) -
    public public

    object

    • 只有一个实例的类
    • 不能自定义构造方法
    • 可以实现接口、继承父类
    • 本质上就是java中最简单的单例

    伴生对象与静态方法

    • 每个类可以对应一个半生对象
    • 半生对象的成员全局独一份(针对类来说的)
    • 半生对象的成员类似java的静态成员

    伴生对象与静态成员

    • 静态成员考虑用包级函数、变量代替(不依赖于某一个类)
    • Java中要调用Kotlin的伴生对象的方法,在Kotlin代码中添加@JvmStatic注解方便调用,调用成员,添加@JvmField
    //Kotlin代码
    package printlin.net
    
    /**
     * @created  2018/11/2 12:06
     * @description:
     * @author sunxiaxia
     */
    fun main(args: Array<String>) {
        val a = minOf(args[0].toInt(), args[1].toInt())
        val latitude2 = Latitude.ofDouble(5.0)
        val latitude = Latitude.ofLatitude(latitude2)
        println(latitude.TAG)
    }
    
    class Latitude private constructor(val value: Double) {
        companion object {
            fun ofDouble(double: Double): Latitude {
                return Latitude(double)
            }
    
            @JvmStatic
            fun ofLatitude(latitude: Latitude): Latitude {
                return Latitude(latitude.value)
            }
        }
        @JvmField
        val TAG:String = "Latitude"
    
    }
    
    //Java代码
    public class JavaStatic {
        public static void main(String...args){
            Latitude latitude = Latitude.Companion.ofDouble(6.0);
            Latitude latitude1 = Latitude.ofLatitude(latitude);
            System.out.println(latitude1.TAG);
        }
    }
    

    方法重载和默认参数

    - 方法重载(Overloads)

    • 名称相同、参数不同的方法
    • Jvm函数签名的概念:函数名、参数列表,跟返回值无关

    默认函数

    • 为函数参数设定一个默认函数
    • 可以为任意位置参数设置默认值
    • 函数调用产生混淆时用具名参数

    方法重载与默认参数

    • 二者的相关性以及@JvmOverloads
    • 避免定义关系不大的重载
    • 不好的设计
    //java中
    List.remove(int)
    List.remove(Object)
    //在Kotlin中
    List.removeAt()=>List.remove(Int)
    List.remove(Object)=>List.remove(Object)
    

    扩展成员

    • 为现有类添加方法,属性
    fun X.y():Z{...}
    val X.m //注意扩展属性不能初始化,类似接口属性
    
    • java调用扩展成员类似调用静态方法:对应的Kotlin类名Kt.方法名
    fun main(args: Array<String>) {
        println("hello".multiply(3))
    }
    fun String.multiply(int:Int):String{
        val stringBuilder  = StringBuilder()
        for (i in 0 until int){
            stringBuilder.append(this)
        }
        return stringBuilder.toString()
    }
    //Java中调用
      ExtendsKt.times("kjhfj",7);
    

    属性代理

    //定义方法
    
    val/var name:Type by expression
    
    • 代理者需要实现相应的setValue/getValue方法
    • lazy原理剖析

    数据类(Data clas,再见JavaBean)

    • 默认实现的copy、toString等方法
    • componentN方法 ,可以自己写
    val (a,b,c) = dataClass实例
    例:
    val person = Person("张丹",35)
        val (a,b) = person
        println("姓名:$a,年龄:$b")
    
    • allOpen和noArg插件,解决数据类被final修饰且没有空的构造函数的问题(dataClass是final,从设计角度上不允许有子类,通过allopen插件可是实现在编译期通过字节码的方式将fianl去掉,通过noArg插件可以实现无参构造方法)
    
    group 'cn.onestravel'
    version '1.0-SNAPSHOT'
    
    
    
    buildscript {
        ext.kotlin_version="1.3.0"
        repositories {
            mavenCentral()
        }
        dependencies {
            classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
            classpath "org.jetbrains.kotlin:kotlin-allopen:$kotlin_version"
            classpath "org.jetbrains.kotlin:kotlin-noarg:$kotlin_version"
        }
    }
    
    apply plugin: 'java'
    apply plugin: 'kotlin'
    apply plugin: 'kotlin-allopen'
    apply plugin: 'kotlin-noarg'
    
    noArg{
        annotation("net.println.demo1.DataBean")
    }
    
    allOpen{
        annotation("net.println.demo1.DataBean")
    }
    
    repositories {
        mavenCentral()
    }
    
    dependencies {
        compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
    
    }
    
    compileKotlin {
        kotlinOptions.jvmTarget = "1.8"
    }
    compileTestKotlin {
        kotlinOptions.jvmTarget = "1.8"
    }
    

    内部类

    • 定义在类内部的类,默认是静态内部类(java默认的是非静态内部类),非静态用inner关键字,与类成员有相似的访问控制
    • 内部类访问外部类的成员用@this@Outter,内部类的成员可以用this@Inner也可以不用。

    匿名内部类

    • 没有定义名字的内部类
    • 类名编译时生成,类似Outter@1.class
    • 可以继承父类、实现多个接口(Java不能同时继承父类又实现接口,要么继承一个类,要么实现一个接口)

    枚举(enmu)

    • 实例可数的类,注意枚举也是类
    • 可以修改构造,添加成员
    • 可以提升代码的表现力,也有一定的性能开销

    密封类(sealed)

    • 子类可数(枚举是实例可数)
    • Kotlin v1.1之前子类必须定义在密封类的内部类
    • v1.1后,子类只需要与密封类在同一个文件中

    相关文章

      网友评论

          本文标题:Kotlin基础(二)——面向对象

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