Scala-泛型

泛型

泛型定义

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<User> userTest = new Test<User>();
     final User t = userTest.t;
     Test userTest1 = new Test();
     final Object t1 = userTest1.t;
    
  • 泛型其实只在编译时有效, 将这个操作称之为"泛型擦除"

     Test<User> userTest = new Test<User>();
     userTest.t = new Emp(); //--> error
     System.out.println(userTest);
    
  • 泛型主要目的是为了约束内部数据的类型

     List list = new ArrayList();
     list.add(new Emp());
     List<User> userList = list;
     // System.out.println(userList);
     for ( User user : userList ) {}
    
  • 泛型和类型不是一个层次,泛型没有所谓的父子关系

    public static void main(String[] args) {
     List<String> stringList = new ArrayList<String>();
     test(stringList); //--> error
     List<Object> stringList1 = new ArrayList<Object>();
     test(stringList1);
    }
    public static void test( Collection<Object> list ) {
     System.out.println(list);
    }
    
  • 泛型的不可变

     public static void main(String[] args) {
     // TODO 6. 泛型的不可变
     List<Child> childList = new ArrayList<Child>(); //--> error
     List<Child> childList1 = new ArrayList<Parent>(); //--> error
     List<Child> childList2 = new ArrayList<SubChild>();
     }
     }
     class Parent {
     }
     class Child extends Parent {
     }
     class SubChild extends Child {
     }
    
  • 为了使用方便,可以定义泛型的边界

    public static void main(String[] args) {
     Producer<Child> p = new Producer<Child>();
     
     p.produce(new Message<Child>());
     p.produce(new Message<Parent>());
     p.produce(new Message<SubChild>()); //--> error
     Consumer<Child> c = new Consumer<Child>();
     final Message<? extends Child> message = c.getMessage();
     final Child data = message.data;
    }
    class Message<T> {
     public T data;
    }
    // 分别给消费者和生产者设置上限与下限
    class Producer<A> {
     public void produce( Message<? super A> message ) {
     }
    }
    class Consumer<B> {
     public Message<? extends B> 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[_ <: Child] = c.consume()
 val data: Child = m.data
 }
 class Message[T] {
 var data : T = _
 }
 class Parent {}
 class Child extends Parent {}
 class SubChild extends Child {}
// 设置上限与下限
 class Producer[T] {
 def produce( message : 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 {
 }
}
作者:POCOPOCOPOCO原文地址:https://www.cnblogs.com/POCOPOCOPOCO/p/16829387.html

%s 个评论

要回复文章请先登录注册