泛型

1. 泛型基础

像 java 一样,Kotlin 中可以拥有类型参数

java实现:

class Box<T>
{
    public T value;
    public Box(T t)
    {
        value = t;
    }

}
public class GenericBasic
{
    public static void main(String[] args)
    {
        List list = new ArrayList();
        list.add("abc");
        list.add(30);
        list.add(true);

        List<String> strList = new ArrayList<>();
        strList.add("abc");
        strList.add("xyz");

        List<Integer> intList = new ArrayList<>();
        intList.add(30);
        intList.add(40);

        Box<Integer> box1 = new Box<>(20);
        Box<String> box2 = new Box<>("abcd");
    }
}

kotlin实现:

//  泛型:泛型基础
class Box1<T>(t:T)
{
    var value = t
}
fun main(args: Array<String>)
{
    var box1:Box1<Int> = Box1(30)
    var box2:Box1<String> = Box1("hello world")

    println(box1.value)
    println(box2.value)
}

2. 类型变异

java 类型系统最棘手的一部分就是通配符类型。但 kotlin 没有,代替它的是两种其
它的东西:声明变化和类型投影(declaration-site variance and type projections)。
首先,我们想想为什么 java 需要这些神秘的通配符。这个问题在Effective Java,条
目18中是这样解释的:使用界限通配符增加 API 的灵活性。首先 java 中的泛型是
不变的,这就意味着 List 不是 List 的子类型。为什么
呢,如果 List 不是不变的,就会引发下面的问题:

// Java
List<String> strs = new ArrayList<String>();
List<Object> objs = strs; // !!! The cause of the upcoming probl
em sits here. Java prohibits this!
objs.add(1); // Here we put an Integer into a list of Strings
String s = strs.get(0); // !!! ClassCastException: Cannot cast I
nteger to String

因此 java 禁止了这样的事情来保证运行时安全。但这有些其它影响。比
如, Collection 接口的 addAll() 方法。这个方法的签名在哪呢?直观来讲
是这样的:

//java
interface Collection<E> ... {
void addAdd(Collection<E> items);
}

但接下来我们就不能做下面这些简单事情了:

//java
void copyAll(Collection<Object> to, Collection<String> from){
to.addAll(from);
}

这就是为什么 addAll() 的签名是下面这样的:

//java
interface Collection<E> ... {
void addAll(Colletion<? extend E> items);
}

这个通配符参数 ? extends T 意味着这个方法接受一些 T 类型的子类而非 T 类
型本身。这就是说我们可以安全的读 T’s (这里表示 T 子类元素的集合),但不能
写,因为我们不知道 T 的子类究竟是什么样的,针对这样的限制,我们很想要这样
的行为: Collection 是 Collection

//  泛型:类型变异

//  out:使用out声明的T只能在获取值的地方使用
//  in:使用in声明的T只能在设置值的地方使用
//  out称为生产者(Producer) clear
//  in称为消费者(Consumer)

abstract class Source<out T>
{
    abstract fun nextT():T
}
fun demo(strs:Source<String>)
{
    val objects:Source<Any> = strs
    println(strs.nextT())
}
abstract class Comparable<in T>
{
    abstract fun compareTo(other:T):Int
}
fun demo1(x:Comparable<Double>)
{
    var a = x.compareTo(1.0)
    val y:Comparable<Double> = x
    println(y.compareTo(2.0))
}

class  AAA : Comparable<Double>(){
    override fun compareTo(other: Double): Int {
        return (other+other).toInt()
    }
}

class  BBB : Source<String>(){
    override fun nextT(): String {
        return "hello"
    }
}


fun main(args: Array<String>)

{
    var mComparable: AAA = AAA()
    var mSource: BBB = BBB()
    demo(mSource)
    demo1(mComparable)
}

3.类型投射(Type Projection)

// 类型投射(Type Projection)
// out和in  out TList<String>可以作为List<Object>的子类型
class MyArray<T>(val size:Int)
{
    fun get(index:Int):T?
    {
        var t:T? = null
        return t
    }
    fun set(index:Int, value:T)
    {

    }
}
/*fun copy(from:MyArray<Any>, to:MyArray<Any>)
{
    //
}*/
//  out的目的就是不允许copy函数修改from的任何数据
// 类型投射
fun copy(from:MyArray<out Any>, to:MyArray<Any>)
{
    //
}
//  类型投射
fun fill(dest:MyArray<in String>, value:String)
{

}
fun main(args: Array<String>)
{
    val ints:MyArray<Int> = MyArray(10)
    val any: MyArray<Any> = MyArray(10)
    copy(ints, any)
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值