一、协变(out)和逆变(in)
/**
* DESC :
* 1.泛型只读模式out
* 2.out T协变 / in T 逆变
*/
const val KtBaseInOrOutTest01_TAG = "KtBaseInOrOutTest01"
class TestOutClass<INPUT>(private val isR: Boolean, vararg objects: INPUT) {
//开启INPUT泛型的只读模式
private val objArr: Array<out INPUT> = objects
//5种返回类型的变化解释
fun getR1() : Array<out INPUT> ? = objArr.takeIf { isR }
//有可能是Array<out INPUT>,也可能是String, 就属于这种Serializable,用Any代替
fun getR2() : Any = objArr.takeIf { isR } ?: "为null了"
//有可能是Array<out INPUT>,也可能是String, 也可能是? 就属于这种Serializable?,用Any?代替
fun getR3() : Any ? = objArr.takeIf { isR } ?: "为null了" ?: null
fun getR4(index: Int) : INPUT ? = objArr[index].takeIf { isR } ?: null
fun getR5(index: Int) : Any ? = objArr[index].takeIf { isR } ?: "AAA" ?: 666 ?: 666.6 ?: 'A' ?: false ?: null
//运算符重载
operator fun get(index:Int) : INPUT ? = objArr[index].takeIf { isR }
/**
* 泛型是很大的类型范围,可以接收很多类型,也可以接受null,但是接受null要处理好
* String? 能够接受"hahah", 还可以接受null,所以String?比String功能要强大
* 小结:异步处理泛型接收,都用String?处理,规范化
*/
fun <INPUT> inputObj(input: INPUT) {
Log.d(KtBaseInOrOutTest01_TAG, "长度为:"+((input as String?)?.length ?: "input为null"))
}
}
//----------------------------------------------------------------------------
/**
* 生产者 out T 协变
* out T 此泛型能够被获取 读取,所以是out
* out T代表整个生产者类里面 这个T只能被读取,不能被修改
*/
interface Producer<out T> {
//不能被修改,编译不通过
// fun consumer(item: T) //消费代码
//只能被读取
fun producer() : T
}
/**
* 消费者 in T 逆变
* in T 此泛型只能被修改,不能读取,所以是in
*/
interface Consumer<in T> {
//只能被修改了
fun consumer(item : T) //消费代码
//不能被读取,编译不通过
// fun producer() : T
}
/**
* 生产者and消费者
*/
interface ProducerAndConsumer<T> {
fun producer() : T//生产代码
fun consumer(item : T) //消费代码
}
//--------------------------------------
open class Animal{}
open class Human : Animal()//人类
open class Man: Human()//男人
open class Women : Human()//女人
//-----------------生产者Producer start--------------------
class ProducerClass1: Producer<Animal> {
override fun producer(): Animal {
Log.d(KtBaseInOrOutTest01_TAG, "Animal...producer==>生产动物")
return Animal()
}
}
class ProducerClass2: Producer<Human> {
override fun producer(): Human {
Log.d(KtBaseInOrOutTest01_TAG, "Human...producer==>生产人类")
return Human()
}
}
class ProducerClass3: Producer<Man> {
override fun producer(): Man {
Log.d(KtBaseInOrOutTest01_TAG, "Man...producer==>生产男人")
return Man()
}
}
class ProducerClass4: Producer<Women> {
override fun producer(): Women {
Log.d(KtBaseInOrOutTest01_TAG, "Women...producer==>生产女人")
return Women()
}
}
//-----------------生产者Producer end--------------------
//-----------------消费者Consumer start--------------------
class ConsumerClass1 : Consumer<Animal> {
override fun consumer(item: Animal) {
Log.d(KtBaseInOrOutTest01_TAG, "Animal...consumer==>消费者动物")
}
}
class ConsumerClass2 : Consumer<Human> {
override fun consumer(item: Human) {
Log.d(KtBaseInOrOutTest01_TAG, "Animal...consumer==>消费者人类")
}
}
class ConsumerClass3 : Consumer<Man> {
override fun consumer(item: Man) {
Log.d(KtBaseInOrOutTest01_TAG, "Animal...consumer==>消费者男人")
}
}
class ConsumerClass4 : Consumer<Women> {
override fun consumer(item: Women) {
Log.d(KtBaseInOrOutTest01_TAG, "Animal...consumer==>消费者女人")
}
}
//-----------------消费者Consumer end--------------------
class KtBaseInOrOutTest01 {
fun testOut01() {
val testOutTest = TestOutClass(true, "你好", 66, 'A')
testOutTest.inputObj("hahha")
testOutTest.inputObj(null)
// testOutTest.inputObj(99)
val r1 = testOutTest.getR1()
val r2 = testOutTest.getR2()
val r3 = testOutTest.getR3()
val r4 = testOutTest.getR4(1)
Log.d(KtBaseInOrOutTest01_TAG, "testOut01==>r1="+r1)
Log.d(KtBaseInOrOutTest01_TAG, "testOut01==>r2="+r2)
Log.d(KtBaseInOrOutTest01_TAG, "testOut01==>r3="+r3)
Log.d(KtBaseInOrOutTest01_TAG, "testOut01==>r4="+r4)
}
/**
* out T 协变
*
* 父类 = 子类(赋值给父类)
*/
fun testInOut01() {
//out T 协变
/**
* 泛型特点:
* 1.默认情况下,泛型的子类对象 不可以赋值给 泛型的父类对象
* 2.加上out,泛型的子类对象 就可以赋值给 泛型的父类对象
* 3.加上out,泛型具体处的子类对象 可以赋值给 泛型声明处的父类对象
*/
val p1 : Producer<Animal> = ProducerClass1()//ProducerClass1本来传递的就是Animal,当然可以
val p2 : Producer<Animal> = ProducerClass2()//ProducerClass2传递Human,也可以,因为是out,去掉out就编译报错了
val p3 : Producer<Animal> = ProducerClass3()//ProducerClass3传递Man,也可以,因为是out
val p4 : Producer<Animal> = ProducerClass4()//ProducerClass4传递Women,也可以,因为是out
val p5: Producer<Man> = ProducerClass3()//ProducerClass3传递Man,赋值给Producer<Man>类型,毫无疑问没问题,有无out都一样
/**
*
* java中写法参考
List<CharSequence> list = new ArrayList<CharSequence>();
//父类 CharSequence, 子类String,不能将String赋值给CharSequence,编译报错
// List<CharSequence> list2 = new ArrayList<String>();
// ? extends T就相当于kt中的out,所以才可以泛型子类对象 赋值给 泛型父类对象
// ? extends CharSequence这样写法就不会报错了
List<? extends CharSequence> list3 = new ArrayList<String>();
*/
}
/**
* in T 逆变
* 子类 = 父类(赋值给子类)
*/
fun testInOut02() {
/**
* in T
* 默认情况下:泛型具体处的父类对象 是不可以赋值给 泛型声明处的子类对象的
* 加上in : 泛型具体处的父类对象 就可以赋值给 泛型声明处的子类对象了
*/
val c1 : Consumer<Animal> = ConsumerClass1()//ConsumerClass1他本来就是传递Animal,当然可以
//以下c2,c3,c4编译报错
// val c2 : Consumer<Animal> = ConsumerClass2()
// val c3 : Consumer<Animal> = ConsumerClass3()
// val c4 : Consumer<Animal> = ConsumerClass4()
val c5: Consumer<Human> = ConsumerClass2()//ConsumerClass2传递Human,当然可以
val c6: Consumer<Man> = ConsumerClass3()//ConsumerClass3传递Man,当然可以
val c6_1 : Consumer<Man> = ConsumerClass2()//ConsumerClass2传递Human,居然也可以,因为in T
val c7: Consumer<Women> = ConsumerClass4()//ConsumerClass4传递Women,当然可以
/**
* 参考java代码
//父类 CharSequence, 子类String
List<CharSequence> list = new ArrayList<CharSequence>();
//父类CharSequence是不可以赋值给子类String的
// List<String> list2 = new ArrayList<CharSequence>();
//使用 ? super T,相当于kt中的in,所以才可以 泛型父类具体处的对象 赋值给 泛型子类声明处的对象
//使用in T, 泛型父类具体处的对象 可以赋值给 泛型子类声明处的对象
List<? super String> list3 = new ArrayList<CharSequence>();
//kt 逆变:子类泛型声明处对象 可以接收 父类泛型具体处对象
*/
}
}
网友评论