Scala-泛型

这篇具有很好参考价值的文章主要介绍了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]]获取隐式变量,如果此时无法查找到对应类型的隐式变量,会发生出错误。文章来源地址https://www.toymoban.com/news/detail-807394.html

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 {
    }
}

到了这里,关于Scala-泛型的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Jmeter接口关联(三)【使用正则表达式提取值】以及正则表达式提取器中模板的含义及用法

    文章目录 前言 一、Jmeter中使用正则表达式匹配 1、选择 RegExp Tester 2、在线程组------》添加------》后置处理器-------里面添加一个“正则表达式提取器” 二、关于正则表达式提取器里面字段的解释 参数说明 三、进一步解释Jmeter正则表达式提取器中的模板 1、当模板设置为$0$ 

    2024年02月13日
    浏览(46)
  • 阶段性复习 迭代器, Lambda表达式, 泛型, 单例模式

        迭代器(Iterator)是一种设计模式,用于顺序访问集合中的元素,而不需要了解集合内部的结构。     迭代器模式将元素的遍历行为和集合类解耦,使得可以在不修改集合类的情况下遍历集合。     具体来说,一个迭代器对象包含了遍历集合所需的状态信息,如当前遍

    2024年02月11日
    浏览(27)
  • String、反射、枚举、lambda表达式以及泛型进阶(数据结构系列16)

    目录 前言: 1. String 1.1 字符串常量池 1.1.1 创建对象的思考 1.1.2 字符串常量池(StringTable) 1.1.3 再谈String对象创建 1.1.4 intern方法 2. 反射 2.1 反射的定义 2.2 反射的用途 2.3 反射的基本信息 2.4 反射相关的类 2.4.1 Class类(反射机制的起源) 2.4.1.1 Class类中的相关方法 2.5 反

    2024年02月11日
    浏览(41)
  • Java自定义泛型类、泛型接口、泛型方法以及 泛型擦除的细节

    体会:使用泛型的主要优点是能够在 编译时 而不是在运行时检测错误。 1.泛型类可能有多个参数,此时应将多个参数一起放在尖括号内。比如:E1,E2,E3 2.泛型类的构造器如下:public GenericClass(){}。而下面是错误的:public GenericClass E (){} 3.实例化后,操作原来泛型位置的结构必

    2024年02月08日
    浏览(32)
  • 泛型方法的定义

    2024年02月05日
    浏览(23)
  • 大数据课程J3——Scala的类定义

    文章作者邮箱:yugongshiye@sina.cn              地址:广东惠州 ⚪ 了解Scala的柯里化 Currying; ⚪ 掌握Scala的类定义; ⚪ 掌握Scala的样例类、option类; ⚪ 掌握Scala的隐式转换机制; 柯里化(Currying)技术 Christopher Strachey 以逻辑学家 Haskell Curry 命名的(尽管它是 Moses Schnfink

    2024年02月12日
    浏览(27)
  • TypeScript 关于对【泛型】的定义使用解读

    泛型 (Generics)是指在 定义函数、接口或类 的时候, 不预先指定具体的类型 ,而在 使用的时候再指定类型 的一种特性 。使用泛型 可以 复用类型并且让类型更加灵活 泛型实现类型参数化: 在定义这个函数时, 我不决定这些参数的类型 而是让调用者以参数的形式告知,我

    2024年02月13日
    浏览(25)
  • TypeScript中的泛型(泛型函数、接口、类、泛型约束)

    一、泛型函数 TypeScript 泛型是一种可以使代码具有更高的可重用性和泛化能力的特性 。通过泛型,我们可以定义一种通用的类型或函数,使其能够应对多种类型的输入。泛型在类、函数、接口等多种场景下都可以使用。 具体来说,在定义泛型函数时,我们可以使用来表示一

    2024年02月11日
    浏览(34)
  • 详解Java中的泛型(泛型的语法,擦除机制,泛型的上界)

    目录 一.什么是泛型 二.Java中为什么要使用泛型 三.泛型的语法 四.泛型类的使用 五.泛型的编译机制(擦除机制) 六.泛型的上界 泛型(Generics)是Java SE 5中引入的一个新特性,可以 使Java中的类和方法具有更广泛的类型范围 。通俗的说,它使得我们可以在定义类和方法时指定

    2024年02月05日
    浏览(40)
  • python中的符号含义

    在Python中,/符号有两种作用: 进行除法运算:当两个操作数都是整数类型时,使用/进行除法运算,结果将会是浮点数类型。例如,5/2的结果是2.5。 执行路径操作:在路径字符串中,/符号用来分隔文件夹和文件名。例如,在Windows系统中,路径可以是’C:/Users/Username/Documents

    2024年02月09日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包