Kotlin学习(六)之-- 对协变out与逆变in的理解和使用(对比Java)

/**
 * 1泛型Animal 是Father的父类,Son1的父类的父类
 * 2泛型Father 是Animal的子类,Son1的父类
 * 3泛型Son1 是Father的子类
 */
open class Animal(var name :String){}
open class Father(name : String) : Animal(name){}
     class Son1(name: String):Father(name){}

一. 协变out
1.1

/** 协变 out*/
interface GetClass<out T>{
    /*** 错误写法*/
//    fun get(pargma:T) : T //out只用去读取,因此不可以做参数去修改,但可以作为返回值去接收
    /**正确写法*/
    fun get() : T
}

1.2

/**
 * out相当于Java的<? extends xx>
 */

class GetClassImp1 : GetClass<Animal> {
    override fun get(): Animal {
        return Animal("Animal")
    }
}

class GetClassImp2 : GetClass<Father>{
    override fun get(): Father {
        return Father("Father")
    }
}

class GetClassImp3 : GetClass<Son1>{
    override fun get(): Son1 {
        return Son1("Son1")
    }
}
    //out:相当于java的<? extends T>,可以接收T和T的子类
    //协变 相当于父类可以接收子类
    var g1 : GetClass<Animal> = GetClassImp1()
    var g2 : GetClass<Father> = GetClassImp2()
    //var g3 : GetClass<Father> = GetClassImp1()//错误写法 声明泛型Father 不可以接收具体泛型 Animal(子类不可以接收父类)
    println(g1.get().name)

Java例子:

        List<CharSequence> list = new ArrayList <String>(); //错误写法
        List<? extends CharSequence> list1 = new ArrayList<String>();//正确写法

二. 逆变 in
1.1

/** 逆变 in*/
interface SetClass<in T>{
    /**错误写法*/
//    fun set(name:String) : T //in只用去修改, 因此不可以作为返回值去接受,但可以作为参数去获取然后修改
    /**正确写法*/
    fun set(pargma : T)

}
class SetClassImp1 : SetClass<Animal> {
    override fun set(pargma: Animal) {
    }
}

class SetClassImp2 : SetClass<Father> {
    override fun set(pargma: Father) {
    }
}

class SetClassImp3 : SetClass<Son1> {
    override fun set(pargma: Son1) {
    }
}

    var i1 : SetClass<Animal> = SetClassImp1()//正确写法
    var i2 : SetClass<Son1> = SetClassImp1()//正确写法,可以接收父类
    var i3 : SetClass<Animal> = SetClassImp2()//错误写法 声明泛型Animal 不可以接收具体泛型 Father(父类不可以接收子类)
    i1.set(Animal("Animal"))

对比Java

        List<String> list2 = new ArrayList<CharSequence>(); //错误写法
        List<? super char> list3 = new ArrayList<CharSequence>(); //正确写法

三.总结
协变out :
1.用于读取操作,得作为返回值,不可以作为参数,类比get()
2.声明泛型时,相当于Java的<? extends T>,可以接收T和T的子类
逆变in:
1.用与修改操作,得作为参数去进行修改,不可以作为返回值,类比set()
2.声明泛型时,相当于Java的<? super T>,可以接收T和T的父类

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值