zoukankan      html  css  js  c++  java
  • scala学习手记35

    先来看一下下面的内容:

    2 days “ago”
    5 days “from_now”

    如上的内容具体应该是什么呢?不过怎么看也不像是代码。不过既然是在学代码,拿不是代码的东西出来做什么!

    非要强说是代码的话,那么执行起来肯定是要报错的——因为scala的Int和RichInt,以及Integer中都没有days这样的方法:

    image

    如果说不是代码的话,那么scala中的to或until本来看起来也不像代码:

    2 to 6
    2 until 7

    现在剩下的就是怎么为整型值添加上days方法。这就涉及到如何扩展整型类了。我自己想了好久也没想到妥帖的法子。

    教材中提供了一个方案,就是采用隐式类型转换。

    隐式类型转换可以帮助我们扩展语言,创建“专用于特定应用和领域”的词汇或语法,也可以帮助我们创建属于自己的领域专用语言。

    关于隐式类型转换,教材上就是这么说的。从这句话里可以看到隐式类型转换为我们留下了巨大的扩展空间。

    先来看看如何解决眼前的事情。要为整型值添加RichInt方法需要先创建一个DateHelper类:

    class DateHelper(number: Int) {
    
      def days(when: String): Date = {
        val date = Calendar.getInstance()
        when match {
          case "ago" => date.add(Calendar.DAY_OF_MONTH, -number)
          case "from_now" => date.add(Calendar.DAY_OF_MONTH, number)
          case _ => date
        }
        date.getTime()
      }
    }

    在DateHelper类中提供了我们需要的days方法。我们要做的就是将给定的数字转换为DateHelper对象。类继承是不行的,强制类型转换也是不行的,可以考虑在需要的时候将整型值转换为DateHelper实例。简单的把方法标记为implicit,只要这个方法在当前范围内存在,scala就会自动调用这个方法:

    implicit def convertInt2DateHelper(number: Int) = new DateHelper(number)

    把上面的代码同DateHelper类一起运行就可以自动将整数值转换为DateHelper实例,然后就可以调用days()方法了。

    来看一下完整的代码:

    import java.util._
    
    class DateHelper(number: Int) {
    
      def days(when: String): Date = {
        val date = Calendar.getInstance()
        when match {
          case "ago" => date.add(Calendar.DAY_OF_MONTH, -number)
          case "from_now" => date.add(Calendar.DAY_OF_MONTH, number)
          case _ => date
        }
        date.getTime()
      }
    }
    
    
    implicit def convertInt2DateHelper(number: Int) = new DateHelper(number)
    
    val ago = "ago"
    val from_now = "from_now"
    
    val past = 2 days ago
    val appointment = 5 days from_now
    
    println(past)
    println(appointment)

    看一下执行结果:

    image

    接下来可以对代码稍作调整。我们并不想在每次需要转换时都去写隐式转换器。把这个转换器放到一个单独的单例对象里,可以获得更好的重用性,也更加易用。可以把转换器挪到DateHelper的伴生对象里:

    import java.util._
    
    class DateHelper(number: Int) {
      def days(when: String): Date = {
        val date = Calendar.getInstance()
        when match {
          case DateHelper.ago => date.add(Calendar.DAY_OF_MONTH, -number)
          case DateHelper.from_now => date.add(Calendar.DAY_OF_MONTH, number)
          case _ => date
        } date.getTime()
      }
    }
    
    object DateHelper {
      val ago = "ago"
      val from_now = "from_now"
    
      implicit def convertInt2DateHelper(number: Int) = new DateHelper(number)
    }

    导入DateHelper时,Scala会自动的找到转换器。这是因为Scala会在当前范围和导入的范围内进行转换。

    在Predef对象里,Scala已经定义了一些隐式转换,Scala会默认导入它们。这样的话,比如说,当我们写1 to 3时,Scala就会隐式的将1从Int转换为其富封装器RichInt,然后,调用to()方法。Scala一次至多应用一个隐式转换。

    在当前范围内,如果发现通过类型转换有助于操作、方法调用或类型转换的成功完成,就会进行转换。

    ######################

  • 相关阅读:
    资料-Java基础:多线程--创建启动线程的多种方式
    资料-Java基础:基础总结-运算符
    资料-Java基础:父子类加载过程
    总结提纲-逐渐补充
    资料-Java基础:类加载处理过程
    资料-Java基础:双亲委派模型
    资料-Java基础:类加载方式及差异
    转载:java 泛型详解-绝对是对泛型方法讲解最详细的,没有之一
    无法启动IIS Express web服务,端口正在使用!
    关于在本地新建数据库作业,无法成功的问题【本地SQLSERVER链接的服务器数据库】
  • 原文地址:https://www.cnblogs.com/amunote/p/5814315.html
Copyright © 2011-2022 走看看