zoukankan      html  css  js  c++  java
  • Scala 操作符与提取器

    实际上Scala没有操作符, 只是以操作符的格式使用方法.
    操作符的优先级取决于第一个字符(除了赋值操作符), 而结合性取决于最后一个字符

    Scala的操作符命名更加灵活:)

    操作符

    中置操作符(Infix)

    a 操作符 b
    

    上述操作符代表一个带有两个参数的方法(一个隐式参数和一个显示参数)

    1 to 10  即 1.to(10) Range
    1 -> 10  即 1.->(10) 对偶操作符(1, 10)    
    

    在自己的类中定义操作符很简单, 以你自己想要做操作符的标识符来定义一个方法就好了.

    class MyOperator(factor1: Int) {
    
        def &@(factor2: Int) = {
            new MyOperator(factor2 * factor1)
        }
        override def toString: String = " " + factor1
    }
    
    object TestMyOp extends App {
        val multi = new MyOperator(4)
        println(multi.&@(2))
    }
    /*output
    8
    */
    

    一元操作符

    后置操作符: 操作符出现在参数之后

    a 操作符
    1 toString 即 1.toString()
    

    前置操作符: 出现在参数之前
    +, -, !, ~ 可以作为前置操作符, 它们被转化为名为 unary_ 的操作符的方法调用
    -a, 即 a.unary_-

    赋值操作符

    形式为

    a 操作符= b  即, a = a 操作符 b
    如 a += b 即: a = a + b
    

    技术细节注意一下:

    • <=, >=, != 不是赋值操作符
    • =开头的操作符不是赋值操作符(==, ===, =/=等)
    • 如果a有一个名为操作符=的方法, 那么该方法会被直接调用, 而不是执行赋值操作

    操作符优先级

    由于Scala可以任意定义操作符, 他需要一套优先级判定方案;
    对所有的操作符生效, 同时保留人们熟悉的标准操作符的优先顺序

    除了赋值操作符之外, 优先级由操作符的首字符决定, 比方说操作符以*开头优先级高于+开头的;

    以下是操作符的首字符的优先级, 从上到下, 优先级依次降低

    首字符优先级
    * / %
    + -
    :
    < >
    ! =
    &
    ^
    |
    非以上操作符

    • 最低优先级的操作符为赋值操作符
    • 出现在同一行的字符所产生的操作符有优先级相同, 比如说 + 和 -> 有着相同的优先级
    • 后置操作符的优先级低于中置操作符

    操作符结合性

    当有一系列的相同优先级的操作符时,操作符的结合性决定了它们从左到右求值还是从右到左求值.

    在Scala中操作符都是左结合的, 除了:

    • 以冒号:结尾的操作符
    • 赋值操作符

    右结合的二元操作符是第二个参数的函数

    2 :: Nil 即 Nil.::(2)
    

    apply, update方法

    f(arg1, arg2, ...)
    

    如果f不是一个函数或者方法, 那么这个表达式等同于调用apply方法, 除非它出现在赋值语句的左侧, 即 f(arg1, arg2, ...) = value, 则调用的是update方法

    f.apply(arg1, arg2, ...)
    
    f.update(arg1, arg2, ..., value)
    

    这机制被用于数组和映射, apply方法常用于伴生对象中, 用来构造对象而不用显式的使用 new 关键字

    val happy = new scala.collection.mutable.HashMap[String, Int]
    happy("smile") = 10 // happy.update("smile", 10)
    happy("smile") // happy.apply("smile")
    

    提取器

    所谓提取器就是一个带有 unapply 方法的对象, 你可以把unapply 方法当成伴生对象中 apply 方法的反向应用, apply 方法接受构造参数, 然后将他们变成对象; 而unapply接受一个对象, 然后从中提取值---这些值就是当时用来构造对象的值.

    每个样例类都自动具备apply和unapply方法

    通常而言, 模式匹配可能会失败, 因此采用 Option 类型作为 unapply 返回值

    object Name extends App{
    
        val me = "wang bin"
        val Name(first, last) = me
        println(first + " " + last)
        println(first)
    
       def unapply(input: String): Option[(String, String)] = {
            val pos = input.indexOf(" ")
            if (pos == -1) None
            else Some((input.substring(0, pos), input.substring(pos + 1)))
            }
        }
    

    带单个参数或者无参数的构造器

    在 Scala 中没有只有一个元素的元组, 如果 unapply 要提取单值, 则它应该返回一个目标类型的 Option[A], 比如下面的 Option[Int]

    object Number extends  App {
    
        val Number(digit) = "1111 "
        println(digit)
        
        def unapply(input: String): Option[Int] = {
            try {
                Some(Integer.parseInt(input.trim))
            } catch {
                case ex: NumberFormatException => None
            }
        }
    }
    

    提取器也可以只是测试其输入而不将值提取出来, 这样的话, unapply 方法应该返回 Boolean. 例如:

    object IsCompound extends App{
        println(NameRes("wang bin"))
        println(NameRes("tom hanks ming"))
        
        def unapply(arg: String):Boolean = arg.contains(" ")
        def NameRes(name: String) = name match {
            //  @ IsCompound() ()不能丢 测试的是 last 是否包含空格
            case Name(first, last @ IsCompound()) => first
            case Name(first, last ) => last
            }
    }
    
    /*output
    bin
    tom
    */    
    

    unapplySeq 方法

    要提取任意长度的值的序列, 我们应该用 unapplySeq 来命名我们的方法, 它返回值为 Option[Seq[A]], 其中 A 是被提取值的类型. 举例来说 Name 提取器可以产出名字中所有组成部分的序列, 这样一来就可以提取任意数量的变量了

    object Name extends App{
    
        val name = "tom li hi"
        println(NameSeq("happy smile"))  // 输出: happly
        println(NameSeq("tom hanks ming toylor")) // 输出 ming
    
        
        def NameSeq(name: String) = name match {
            //  @ IsCompound() ()不能丢 测试的是 last 是否包含空格
            case Name(first, last) => first
            case Name(first, "good",  last ) => last
            case Name(first, nd, rd, _*) => rd
            case _ => "NameSeq"
        }
        
        def unapplySeq(input: String): Option[Seq[String]] = {
                if (input.trim == "") None else Some(input.split("\s+"))
            }
    }
    



  • 相关阅读:
    发送指令
    WIN32得到HWND
    查找摄像头
    WindowImplBase::OnSysCommand-------duilib在最大化和还原间切换
    CImage将图片转为指定像素大小
    聚集索引和非聚集索引(整理)
    数据库SQL优化大总结之 百万级数据库优化方案
    架构师之路(39)---IoC框架
    .NET Reflector反编译的方法
    PowerDesigner之PDM(物理概念模型)
  • 原文地址:https://www.cnblogs.com/nowgood/p/scalaoperator.html
Copyright © 2011-2022 走看看