美文网首页FS全栈计划
利用Scala的隐式转换,扩展对象方法

利用Scala的隐式转换,扩展对象方法

作者: MaxZing | 来源:发表于2019-01-19 17:14 被阅读0次

    Int对象是没有判断当前数是不是质数的方法的,所以一般都是直接写在方法里去判断,或者抽离成方法去调用,举个例子

    原始方式

     //1-100内的质数
    import util.control.Breaks._
    object NumberTest {
      def printEven() = {
        for (i <- 0 to 100) {
          breakable {
            i match {
              case i if i < 1 => break
              case 1 | 2 | 3 => print(i + ",")
              case i if (canNotExcept(i)) => print(i + ",")
              case _ => break
            }
          }
        }
      }
    
      def canNotExcept(i: Int): Boolean = {
        val half = i / 2
        var flag = true
        breakable {
          for (n <- 2 to half) {
            if (0 == i % n) {
              flag = false
              break
            }
          }
        }
        flag
      }
    }
    

    隐式转换转换方式

    如果想让Int直接带有判断质数的能力,基本不太可能
    但是如果换一种思路:把Int转换成一个能判断自己是不是质数的类型,就好了啊

    转换类

        implicit class IntUtil(i: Int) {
          // 判断数字为质数
          def isPrime: Boolean = {
            i match {
              case i if 1 > i => false
              case 1 | 2 | 3 => true
              case i => {
                val half = i / 2
                if (except(half)) false else true
              }
            }
    
          }
    
          // 判断数字不是质数
          def isNotPrime: Boolean = !isPrime
    
          //尾递归,判断能佛被比divisor小的数整除
          @tailrec
          final def except(divisor: Int): Boolean = {
            if (2 == divisor )  0 == i % divisor
            else if (0 == i % divisor) true
            else except(divisor - 1)
          }
        }
    

    使用更方便

    import util.control.Breaks._
    // 引入自定义的隐式转换
    import com.zing.my.IntUtil._
    
    object NumberTest {
      def printEven() = {
    
        for (i <- 0 to 100) {
          breakable {
    // i 会直接隐式转换成IntUtil类型,然后就可以使用isNotPrime方法了
            if (i.isNotPrime) {
              break
            }
            print(i + ",")
          }
        }
      }
    }
    

    小结

    大佬说,尾递归是函数式编程的精髓之一,而隐式转换是Scala的精髓之一。我玩Scala大约一周了,暂时的体会是用起来真爽,看起来真难懂。
    本文展示了使用隐式类型,帮助扩展原有类的方法,虽然实质上是把原有类型转换成新类型,但是写起来看着就是方法被扩展了。

    优点是:

    • 可以更加方便的对类型进行扩充,不限于方法,也可以是属性,方法参数等
    • 合适情况下可读性也更强,更加专注于逻辑而不是实现细节

    缺点是:

    • IDEA无法自动帮你导入隐式函数或者类,只能自己手工来
    • 不合适的情况下大佬隐藏了细节,导致初学者完全不知道为什么直接就调用到了方法。不知> 道实现的逻辑

    隐式转换的原理其实就是编译器发现编译不能直接进行,再尝试你导入的隐式转换,转换成功了就编译成转换后的结果,不成功,那就真的不成功了。

    PS: 这里的break是一个方法哦,Scala是没有breakcontinue

    参考

    工具书:《Scala编程 第三版》

    喜欢请点个赞
    转载请注明出处:https://www.jianshu.com/u/4915ed24d1e3
    如有错误,请务必指正。谢谢
    我的博客:https://xzing.github.io/

    相关文章

      网友评论

        本文标题:利用Scala的隐式转换,扩展对象方法

        本文链接:https://www.haomeiwen.com/subject/almodqtx.html