Kotlin基础学习记录——面向对象(下)

Kotlin基础学习记录

面向对象(下)

1.扩展

扩展方法 fun 被扩展类名().方法名()

open class Raw {
    fun test() {
        print("test方法")
    }
}

class SubRaw : Raw() {
    fun sub() {
        print("sub方法")
    }
}

fun Raw.info() {
    print("===扩展的info方法===")
}

fun main() {
    //扩展后Raw可以调用info;SubRaw也可以调用info
    var t = Raw()
    t.test()
    t.info()
    var s = SubRaw()
    s.sub()
    s.test()
    s.info()
}

扩展的实现机制

本质上是定义了一个函数,当程序调用对象的扩展方法时,根据调用对象、方法名找到扩展函数,转换为函数调用
调用扩展方法由所在表达式的编译时类型决定
成员方法执行动态解析,扩展方法执行静态解析
成员方法优先级高于扩展方法
java调用扩展方法:

    public void test(){
        Raw raw = new Raw();
        raw.test();
//        raw.info(); 错误
        RawKt.info(raw); //正确 文件名为Raw.kt,这里写为RawKt
    }

可空类型的扩展方法

需要处理null值的情形
例:

//Raw.kt文件
fun Any?.ee(other:Any?):Boolean{
    if (this==null)
        return if (other==null) true else false
    return this.equals(other)
}
//Java调用时
RawKt.ee("as",null)

扩展属性

扩展的属性只能是计算属性

  • 不能有初始值(没有存储属性的幕后字段)
  • 不能用field关键字显式访问幕后字段
  • 扩展只读属性必须提供getter方法,读写属性提供setter、getter方法

示例:

//Raw.kt文件
class User1(var firstName:String, var lastName:String){}
var User1.fullName:String
    get() = "${firstName}.${lastName}"
    set(value) {firstName = value}
//Java调用时
User1 user = new User1("A","B");
RawKt.setFullName(user,"C");
System.out.println(RawKt.getFullName(user))

以成员方式定义扩展

以类成员的方式定义扩展(定义方法、属性的方式)

  • 属于被扩展的类,可以直接调用被扩展类的成员(省略this)
  • 位于定义它所在的类的类体中,可以直接调用所在类的成员(省略this)
class A {
    var t = "A的属性t"
    fun test() {
        println("A的test方法")
    }
}

class B {
    var s = "B的属性s"
    var t = "B的属性t"
    fun test() {
        println("B的test方法")
//        var a = A()
//        a.extension() //OK
    }

    fun A.extension() {
        println("A的extension方法Start")
        println(t)//A的属性t
        println(this@B.t)//B的属性t
        println(s)//B的属性s
        println("A的extension方法End")
    }

    fun invokeMethod(target: A) {
        test()//B的test方法
        target.test()A的test方法
        target.extension()
    }
}

fun my() {
    var b = B()
    b.test()//B的test方法
    b.invokeMethod(A())
//    var a = A()
//    a.extension()//ERROR
}

//output:
//B的test方法
//B的test方法
//A的test方法
//A的extension方法Start
//A的属性t
//B的属性t
//B的属性s
//A的extension方法End

总结:

  1. 扩展方法A.extension()可以直接调用被扩展类A以及所在类B的成员,若有冲突,被扩展类优先A.extension中的println(t)输出为"A的属性t"),若要执行所在类的成员可使用带标签的this进行限定(如:println(this@B.t)
  2. B中可以调用a.extension()方法,但外部的方法(包括A)似乎必须通过BinvokeMethod()才能访问extension
    3. 目 前看来这个功能似乎有点繁琐,不知道有什么应用场景??

带接收者的匿名函数

支持为类扩展匿名函数

val f = fun A.(): Int {
    return 6
}
//调用
A().f()

何时使用扩展

现阶段我还没什么感觉,可能以后再看会有一些感想吧

2.final和open修饰符

final:

  1. 默认final
  2. 修饰的类、属性、方法不可变
  3. 不可以修饰局部变量

疑问:属性不是由var|val决定了是否可变?
final表明能否被重写,在继承关系里,可变与不可变是另一个维度

可执行“宏替换”的常量

const修饰

final属性、final方法、final类

属性默认为final,方法默认为final
注意是重写还是重定义
类默认为final,不能被继承

3.抽象类

abstract修饰符
和Java类似

密封类

特殊的抽象类,其子类是固定的
密封类的子类必须与密封类在同一个文件中,间接子类无须在同一文件中

sealed class Apple {
    abstract fun taste()
}

open class RedFuji : Apple() {
    override fun taste() {
        TODO("Not yet implemented")
    }
}

4.接口

多继承
可以包含非抽象方法
不需要被重写的成员支持private

5.嵌套类和内部类

嵌套类:相当于静态内部类
内部类:非静态内部类

6.对象表达式和对象声明

object[:0~N个父类型]{
    //对象表达式的类体部分
}
  • 不能是抽象类
  • 不能定义构造器(可以定义初始化块)
  • 可以包含内部类,不能包含嵌套类

//TODO 待完成

7.枚举类

//TODO 待完成

8.类委托和属性委托

//TODO 待完成

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值