kotlin 多态和扩展

1. 多态

当我们用一个子类继承一个父类的时候。这就是子类型多态。另一个多肽是参数化类型,也就是泛型。此外,C++的运算符重载叫特色多态。
用子类型替换超类型实例的行为就是我们通常说的子类型多态。

1.1 对第三方类进行扩展

假使当对应的业务类A和B是第三方引入的,且不可被修改时。如果我们想要给他扩展一些方法。比如将对象转化为json。利用之前介绍的多态技术就显得比较麻烦。


fun ClassA.toJson():String{
}

kotlin支持扩展的语法。利用扩展,我们就能给当前类添加方法和属性,从而换一种思路来解决上面的问题扩展属性和方法的实现运行在A实例上。他们的定义操作并不会修改类的本身。这样就为我们带来了一个很大的好处,及被扩展的第三方类免于被污染。从而避免一些因负累修改而可能导致此类出错的问题发生

2 特设多态和运算符重载

基本数据一般可以直接运算,但是对象之间就没法直接参与运算。

data class Area(val value:Area)

opertor fun Area.plus(that:Area):Area{
	return Area(this.value+thar.value)
}

我们可以采用扩展的语法来解决问题。此外,kotlin原生支持了一种语言特性来很好地解决问题,这就是运算符重载

Operator它的作用是将一个函数标记为重载一个操作符或者实现一个约定。除了重载加法,我们还可以通过重载减法、乘法、除法、取余等函数来实现重载运算符。

a in b // b.contains(a)

3. 扩展函数

3.1 开放封闭原则

对开发者而言,业务需求总是在不断变动。在修改现有代码的时候,我们应该遵循开放封闭原则及软件,实际应该是可扩展。而不可修改的。也就是说,对扩展开放,对修改封闭

开放、封闭原则是所有面向对象原则的核心。软件设计本身所追求的目标就是封装变化、降低耦合,而开放封闭原则正是这一目标的直接体现

但是在我们实际开发当中,为了实现某个需求,引入了一个第三方库。但某一天,需求发生了变化,当前库无法满足,也许你就会尝试对库源码进行修改,这就违背了开放封闭原则。

3.2 使用扩展函数

扩展函数需要一个前缀,就是接受者类型,通常为类和接口的名称。
This代表的是接收者类型的对象

     fun MutableList<Int>.exchange(fromIndex:Int,toIndex:Int){
        val temp = this[fromIndex]
        this[fromIndex]= this[toIndex]
        this[toIndex] = temp
    }

对应的Java代码为:

public final class TestMethodKt {
   public static final void exchange(@NotNull List $this$exchange, int fromIndex, int toIndex) {
      Intrinsics.checkNotNullParameter($this$exchange, "$this$exchange");
      int temp = ((Number)$this$exchange.get(fromIndex)).intValue();
      $this$exchange.set(fromIndex, $this$exchange.get(toIndex));
      $this$exchange.set(toIndex, temp);
   }
}

我们可以把扩展函数理解为静态方法,静态方法独立于该类的任务对象,且不依赖类的特定实例,被该类的所有实例共享。

3.3.扩展函数的作用域

通常扩展函数直接定义在一个包内,也就是直接写入到kt文件内。
如果需要再其他包中调用,只需要Import相应的方法即可。

Package com.example.extension

     fun MutableList<Int>.exchange(fromIndex:Int,toIndex:Int){
        val temp = this[fromIndex]
        this[fromIndex]= this[toIndex]
        this[toIndex] = temp
    }

如果我们也可能将扩展函数定义在一个Class内部统一管理。

class Extends{
	  fun MutableList<Int>.exchange(fromIndex:Int,toIndex:Int){
        val temp = this[fromIndex]
        this[fromIndex]= this[toIndex]
        this[toIndex] = temp
    }
}

转移成Java代码

public final class Extends {
   public final void exchange(@NotNull List $this$exchange, int fromIndex, int toIndex) {
      Intrinsics.checkNotNullParameter($this$exchange, "$this$exchange");
      int temp = ((Number)$this$exchange.get(fromIndex)).intValue();
      $this$exchange.set(fromIndex, $this$exchange.get(toIndex));
      $this$exchange.set(toIndex, temp);
   }
}

这时候发现不是静态方法了。外部无法调用了。这时候只能在该类和该类的子类中可以调用。

3.4 扩展属性

和扩展函数一样,扩展属性本质就是对应Java的静态方法。
扩展函数不能有默认值:因为扩展熟悉没有实际地将成员插入类中,因此对扩展属性来说幕后字段是无效的。

    val MutableList<Int>.sumIsEven: Boolean
        get() = this.sum() % 2 == 0

转换为Java

 public static final boolean getSumIsEven(@NotNull List $this$sumIsEven) {
      Intrinsics.checkNotNullParameter($this$sumIsEven, "$this$sumIsEven");
      return CollectionsKt.sumOfInt((Iterable)$this$sumIsEven) % 2 == 0;
   }

3.5 扩展特殊情况

1. 给静态对象添加扩展函数

class Son {
    companion object{
        val age = 19
    }
}

fun Son.Companion.foo(){
    print("age= $age")
}

2. 成员方法优先级高于扩展函数

当类中已经有了一个方法,扩展函数还是当前方法,当调用test1的时候,优先调用成员方法

class Son {
    fun test1(){
        print("test1")
    }
}

fun Son.test1(){
    print("extension")
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值