scala 泛型上下限、协变、逆变

  • Post author:
  • Post category:其他


首先说明,我是学java的,暂时现在java还是我的本命语言,也就说,对java语法滚瓜烂熟,其他语言语法就随便用用,细节没记。所以,学习scala时都是用于转换成java的思维去理解(scala代码转class字节码再转java代码,一样能走通不是么,了解底层,就不用想太多了,节省时间)

重点来了,这里记录一下学习scala泛型相关的东西。。就是与java泛型的做个对比。。

一、上下限。

java是使用extends与super。

而scala是使用<:与>:

功能是一模一样的。(所以这两门jvm语言为什么关键字不同一一下?)

那我就不多讲了。

二、scala协变、逆变与java的通配符+extends、super

scala协变与逆变是在类型定义泛型的时候指定。。分别是协变是在泛型参数前用+,逆变在泛型参数前用-号。

java的不详细描述。

首先看scala的逆变与协变代码:

object Test {
    def main(args: Array[String]): Unit = {
        var t1:Test1[Father] = new Test1[Son]
        var t2:FatherTest[Father] = new Test1[Son]  //java无法做到
        var t3:Test2[Father] = new Test2[GrandFather]
    }
}
class Son extends Father {}
class Father extends GrandFather {}
class GrandFather{}

class FatherTest[+T]{}
//协变
class Test1[+T] extends FatherTest {}
//逆变
class Test2[-T]{}

再看看java的代码:

public class Main  {
    public static void main(String[] args) {
        Test1<? extends Father> t1 = new Test1<Son>();
        //java不能做到下面一行,scala可以
        //TestFather<? extends Father> t2 = new Test1<Son>();
        Test2<? super Father> t3 = new Test2<GrandFather>();
    }
}

class Son extends Father { }
class Father extends GrandFather { }
class GrandFather{ }

class TestFather<T>{}
class Test1<T> extends FatherTest<T> {}
class Test2<T>{}

其实两者意思差不多。。

区别在于scala协变与逆变是写在类型定义的时候。。java的则在代码赋值时才用通配符。

但他们都是为了在赋值时可以让同一变量接收不同泛型。

只不过,scala可以类型不同、泛型也不同,但都必须由继承关系才行。而java则类型必须相同,泛型可以不同,只需泛型有继承关系即可。

总的来说,scala的范围更大一些,java范围小一些。



版权声明:本文为qq_36951116原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。