zoukankan      html  css  js  c++  java
  • Scala进阶之路-Scala中的高级类型

                  Scala进阶之路-Scala中的高级类型

                                作者:尹正杰

    版权声明:原创作品,谢绝转载!否则将追究法律责任。

    一.类型(Type)与类(Class)的区别

      在Java里,一直到jdk1.5之前,我们说一个对象的类型(type),都与它的class是一一映射的,通过获取它们的class对象,比如 String.class, int.class, obj.getClass() 等,就可以判断它们的类型(type)是不是一致的。简单的说Type是用来描述类的,而Class是用来描述类的,因此Tpye范围要比Class描述的范围要更大一些!

      而到了jdk1.5之后,因为引入了泛型的概念,类型系统变得复杂了,并且因为jvm选择了在运行时采用类型擦拭的做法(兼容性考虑),类型已经不能单纯的用class来区分了,比如 List<String> 和 List<Integer> 的class 都是 Class<List>,然而两者类型(type)却是不同的。泛型类型的信息要通过反射的技巧来获取,同时java里增加了Type接口来表达更泛的类型,这样对于 List<String>这样由类型构造器和类型参数组成的类型,可以通过 Type 来描述;它和 List<Integer> 类型的对应的Type对象是完全不同的。

      在Scala里,类型系统又比java复杂很多,泛型从一开始就存在,还支持高阶的概念(后续会讲述)。所以它没有直接用Java里的Type接口,而是自己提供了一个scala.reflect.runtime.universe.Type(2.10后)。

     1 /*
     2 @author :yinzhengjie
     3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Scala%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
     4 EMAIL:y1053419035@qq.com
     5 */
     6 package cn.org.yinzhengjie
     7 
     8 import scala.reflect.runtime.universe._
     9 
    10 class Teacher(name:String,age:Int){
    11 
    12 }
    13 
    14 object AdvancedType {
    15     def main(args: Array[String]): Unit = {
    16         /**
    17           * 注意,typeOf 和 classOf 方法接收的都是类型符号(symbol),并不是对象实例。
    18           */
    19         val typeInfo = typeOf[Teacher]                //在scala里获取类型信息是比较便捷的
    20         println(typeInfo)
    21 
    22         val classInfo = classOf[Teacher]             //同样scala里获取类(Class)信息也很便捷
    23         println(classInfo)
    24     }
    25 }
    26 
    27 
    28 /*
    29 以上代码执行结果如下:
    30 cn.org.yinzhengjie.Teacher
    31 class cn.org.yinzhengjie.Teacher
    32  */

    二.classOf与getClass的区别

      获取Class时的两个方法:classOf 和 getClass。

      这种细微的差别,体现在类型赋值时,因为java里的 Class[Teacher]是不支持协变的,所以无法把一个Class[_ < : Teacher] 赋值给一个 Class[Teacher]。

    三.结构类型

      结构类型是指一组关于抽象方法、字段和类型的规格说明,你可以对任何具备play方法的类的实例调用play方法,这种方式比定义特质更加灵活,是通过反射进行调用的。简单来说,就是只要是传入的类型,符合之前定义的结构的,都可以调用。

     1 /*
     2 @author :yinzhengjie
     3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Scala%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
     4 EMAIL:y1053419035@qq.com
     5 */
     6 package cn.org.yinzhengjie
     7 
     8 class Structure {
     9     def play() = println("play方法调用了")
    10 }
    11 
    12 
    13 
    14 object AdvancedType extends App {
    15     /**
    16       * type关键字是把 = 后面的内容命名为别名。
    17       */
    18     type X = {
    19         def play(): Unit
    20     }
    21 
    22     /**
    23       * 定义本地方法,将X类型传入
    24       */
    25     def init(res: X) = {
    26         res.play
    27     }
    28 
    29     /**
    30       * 调用init的方法,需要传入一个实现X对象的paly方法
    31       */
    32     init(new {
    33         def play() = println("Play再一次")
    34     })
    35 
    36 
    37     /**
    38       * 结构类型,简单来说,就是只要是传入的类型,符合之前定义的结构的,都可以调用。
    39       */
    40     object A {
    41         def play() {
    42             println("A object play")
    43         }
    44     }
    45 
    46     init(A)
    47 
    48     val structure = new Structure
    49     init(structure)
    50 }
    51 
    52 
    53 /*
    54 以上代码执行结果如下:
    55 Play再一次
    56 A object play
    57 play方法调用了
    58  */

    四.中置类型

     1 /*
     2 @author :yinzhengjie
     3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Scala%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
     4 EMAIL:y1053419035@qq.com
     5 */
     6 package cn.org.yinzhengjie
     7 
     8 object AdvancedType extends App {
     9     /**
    10       * 中置类型是一个带有两个类型参数的类型,以中置语法表示,比如可以将Map[String, Int]表示为:
    11       */
    12     val scores: String Map Int = Map("yinzhengjie" -> 100)
    13     println(scores)
    14 }
    15 
    16 
    17 /*
    18 以上代码执行结果如下:
    19 Map(yinzhengjie -> 100)
    20  */

    五.自身类型

      对于this别名 yinzhengjie=>这种写法形式,是自身类型(yinzhengjie type)的一种特殊方式。yinzhengjie在不声明类型的情况下,只是this的别名,所以不允许用this做this的别名。案例如下:

     1 /*
     2 @author :yinzhengjie
     3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Scala%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
     4 EMAIL:y1053419035@qq.com
     5 */
     6 package cn.org.yinzhengjie
     7 
     8 class A {
     9     /**
    10       *         yinzhengjie => 这句相当于给this起了一个别名叫yinzhengjie,
    11       * 注意 : yinzhengjie并不是关键字,可以用除了this外的任何名字命名(除关键字)。
    12       */
    13     yinzhengjie =>
    14     val x = 100
    15     def foo = yinzhengjie.x + this.x
    16 }
    17 
    18 
    19 /**
    20   * 注意,这里的yinzhengjie是给外部的Outer起了一个别名叫做yinzhengjie
    21   */
    22 class Outer { yinzhengjie =>
    23     val v1 = "here"
    24     //定义一个Scala内部类
    25     class Inner {
    26         val v1 = "there"
    27         println(yinzhengjie.v1) // 用yinzhengjie表示外部类(起了个别名),相当于Outer.this.v1
    28     }
    29     new Inner
    30     println(this.v1)
    31     println(Outer.this.v1)
    32 }
    33 
    34 
    35 object AdvancedType extends App {
    36     new Outer
    37 
    38     val res = new A
    39    println(res.foo)
    40 }
    41 
    42 
    43 /*
    44 以上代码执行结果如下:
    45 here
    46 here
    47 here
    48 200
    49  */

    六.运行时反射

      关于Scala高级类型还有很多,我这里就不一一列举啦,比如:复合类型,类型别名,类型投影,单例类型等等。对了,关于反射的笔记请参考:https://www.cnblogs.com/yinzhengjie/p/9385123.html

  • 相关阅读:
    常用输入框组组合
    Select2的远程数据操作
    利用Mocking Framework 单元测试Entity Framework
    Newtonsoft.Json在转换指定时间格式时默认是UTC时间
    对于使用jquery,chosen,easyui统一进行页面元素禁用公共方法
    SQL_ORACLE速记---比较两张表的数据类型和数据长度是否一致;导出数据表类型和长度
    js常用方法速记
    前端发起Ajax,MVC中的Action却接收不到参数
    base 和 this
    方法
  • 原文地址:https://www.cnblogs.com/yinzhengjie/p/9399062.html
Copyright © 2011-2022 走看看