泛型泛型定义
Scala的泛型和Java中的泛型表达的含义都是一样的,对处理的数据类型进行约束,但是Scala提供了更加强大的功能
scala中的泛型采用中括号
scala中的泛型是不可变的
泛型和类型不是一个层面的东西
所以scala中泛型和类型无法联合使用
泛型语法
如果能将类型和泛型当成一个整体来使用的话,那不就方便了吗?
如果将类型和泛型联合使用,那么类型相同时,如果泛型存在父子类关系,那么联合的类型也就存在父子类关系,这个操作其实就是一种变化,称之为协变, +T
如果类型相同,泛型之间存在父子关系,那么让联合后的类型存在子父关系。这个操作其实也是一种变化,称之为逆变, -T
val message1 : Message[Child] = new Message[Child]()val message2 : Message[Child] = new Message[Parent]()//val message3 : Message[Child] = new Message[SubChild]() -- 不符合新的父子关系// Child(父) -> child -> SubChild(子)// MessageChild(子) MessageSubChild(父)// Child(子) Parent(父)// MessageChild(父) MessageParent(子)class Message[-T] {}class Parent {}class Child extends Parent {}class SubChild extends Child {}
泛型和类型的区别
- 所谓的类型,其实就是对外部的数据做约束
- 所谓的泛型,其实就是对内部的数据做约束
泛型特征
泛型和类型的层次不一样。不能作为整体来考虑
泛型在某些场合中,其实就是类型参数,用于向类中传递参数
Test userTest = new Test(); final User t = userTest.t; Test userTest1 = new Test(); final Object t1 = userTest1.t;
泛型其实只在编译时有效, 将这个操作称之为”泛型擦除”
Test userTest = new Test(); userTest.t = new Emp(); //--> error System.out.println(userTest);
泛型主要目的是为了约束内部数据的类型
List list = new ArrayList(); list.add(new Emp()); List userList = list; // System.out.println(userList); for ( User user : userList ) {}
泛型和类型不是一个层次,泛型没有所谓的父子关系
public static void main(String[] args) { List stringList = new ArrayList(); test(stringList); //--> error List
泛型的不可变
public static void main(String[] args) { // TODO 6. 泛型的不可变 List childList = new ArrayList(); //--> error List childList1 = new ArrayList(); //--> error List childList2 = new ArrayList(); } } class Parent { } class Child extends Parent { } class SubChild extends Child { }
为了使用方便,可以定义泛型的边界
public static void main(String[] args) { Producer p = new Producer(); p.produce(new Message()); p.produce(new Message()); p.produce(new Message()); //--> error Consumer c = new Consumer(); final Message message = c.getMessage(); final Child data = message.data;}class Message { public T data;}// 分别给消费者和生产者设置上限与下限class Producer { public void produce( Message message ) { }}class Consumer { public Message getMessage() { return null; }}
泛型的上限与下限
Scala的泛型可以根据功能设定类树的边界
这里的上限和下限采用的是颜文字
def main(args: Array[String]): Unit = { val p = new Producer[Child] p.produce(new Message[Child]) p.produce(new Message[Parent]) p.produce(new Message[SubChild]) // --> error val c = new Consumer[Child] val m: Message[_ : T] ): Unit = { } } class Consumer[T] { def consume(): Message[_ <: T] = { null } }
集合的泛型
使用时需甄别源码 看是否有上限下限
def main(args: Array[String]): Unit = { val list : List[Child] = List( new Child(), new Child(), new Child() ) // 集合中函数要遵守继承 list.fold[Parent](new Parent)( (x,y) => x ) // 但left不需要考虑继承 list.foldLeft[SubChild](new SubChild)((x, y) => x) }class Parent {}class Child extends Parent {}class SubChild extends Child {}
上下文限定
上下文限定是将泛型和隐式转换的结合产物,以下两者功能相同,使用上下文限定[A : Ordering]之后,方法内无法使用隐式参数名调用隐式参数,需要通过implicitly[Ordering[A]]获取隐式变量,如果此时无法查找到对应类型的隐式变量,会发生出错误。
object ScalaGeneric { def main(args: Array[String]): Unit = { def f[A : Test](a: A) = println(a) implicit val test : Test[User] = new Test[User] f( new User() ) } class Test[T] { } class Parent { } class User extends Parent{ } class SubUser extends User { }}