11 操作符

  • 标识符由字母、数字、运算符组成
  • 一元和二元操作符其实是方法调用
  • 操作符优先级取决于第一个字符,结合性取决于最后一个字符
  • apply和update方法在对expr(args)表达式求值时被调用
  • 提取器从输入中提取元组或值的序列
  • 扩展自Dynamic特质的类型可以在运行期检视方法名和入参

标识符

  • 变量、函数、类等的名称统称为标识符。
  • 可以使用Unicode字符
  • 还是使用字母数字下划线那些吧,不用那些乱七八糟的符号了。
  • 反引号中可以包含几乎任何字符序列
scala> val `for`=10
for: Int = 10

中置操作符

  • a 标识符 b,其中标识符为一个带有两个参数的方法,一个隐式参数,一个显式参数
  • 例如,1 to 10是一个方法的调用1.to(10),这就是中置表达式,操作符位于两个参数之间
  • 分数的乘法,Fraction类
class Fraction(n:Int,d:Int){
  private val num = n
  private val den = d
  def *(other:Fraction):Fraction={
    new Fraction(num*other.num,den*other.den)
  }
  override def toString: String = s"${num}/${den}"
}
//使用
val a1 = new Fraction(3,4)
val a2 = new Fraction(4,6)
val x = a1 * a2
val y = a1.*(a2)

一元操作符

  • 只有一个参数的操作符是一元操作符,中置操作符是二元的,有两个参数
  • 前置操作符:+ - ! ~共四个,标识符a被转换为a.unary_操作符的方法调用。
scala> 1.unary_-
res3: Int = -1

scala> 1.unary_~
res4: Int = -2
  • 后置操作符,一元操作符跟在参数后面,a标识符转换为a.标识符()的方法调用,使用后置操作符会有警告,可以使用import scala.language.postfixOps关闭警告。后置操作符可能会引发解析错误。
scala> 43.toString()
res7: String = 43

scala> 43 toString
warning: there was one feature warning; re-run with -feature for details
res8: String = 43

赋值操作符

  • 形式为 a 操作符= b等同于a = a 操作符 b,例如a += b 等同于a = a + b
  • 注意:
  1. <=、>=、!=不是赋值操作符
  2. 以=开头的操作符不是赋值操作符(==、 === 、=/=)
  3. 如果a有一个名为操作符=的方法,那么该方法会被直接调用

优先级

  • 一次使用多个操作符且没有用括号时,高优先级的操作符先执行
  • 除赋值操作符外,优先级由操作符的首字符决定
  • 出现在同一行字符产出的操作符优先级相同,例如+->有相同的优先级
  • 后置操作符优先级低于中置操作符
最高优先级:除以下字符外的操作符字符
* / %
+ -
:
< >
! =
&
^
|
非操作符的其他符号
最低优先级:赋值操作符

结合性

  • 右结合从右往左算,左结合从左往右算
  • 右结合的:
  1. 以冒号结尾的操作符
  2. 赋值操作符
  • 左结合:除了右结合以为的操作符

apply和update方法

  • f(arg1,arg2,…,argn)等同于f.apply(arg1,arg2,…,argn),在f不是函数或方法的时候
  • f(arg1,arg2,…,argn)=value等同于f.update(arg1,arg2,…,argn,value)
  • 经常被用于数组和映射
  • apply方法经常被用于伴生对象中,构造对象的时候就不用显示地用new了。apply方法的参数使用构造器的参数。
  • 下面的例子中,两个参数表示分数,三个参数表示带分数,现在可以直接用Fraction(2,3)和Fraction(2,3,2)
class Fraction (n:Int,d:Int){
  private var num = n
  private var den = d
  
  def this(x:Int,n:Int, d:Int){
    this(n,d)
    num = x * d + n
  }
  
  def *(other:Fraction):Fraction={
    new Fraction(num*other.num,den*other.den)
  }
  
  override def toString: String = s"${num}/${den}"
}

object Fraction{
  def apply(n: Int, d: Int): Fraction = new Fraction(n, d)
  def apply(x:Int,n: Int, d: Int): Fraction = new Fraction(x,n, d)
}

提取器 unapply方法

  • 提取器是带有unapply方法的对象,看做apply方法的逆操作。
  • apply接受参数构造对象,unapply方法接受一个对象,然后从中提取值。unapply方法返回的是一个Option对象
  • 每一个样例类case class自动拥有一个apply和unapply方法
class Fraction (n:Int,d:Int){
  private var num = n
  private var den = d
  def this(x:Int,n:Int, d:Int){
    this(n,d)
    num = x * d + n

  }
  def *(other:Fraction):Fraction={
    new Fraction(num*other.num,den*other.den)
  }

  override def toString: String = s"${num}/${den}"
}
object Fraction{
  def apply(n: Int, d: Int): Fraction = new Fraction(n, d)
  def apply(x:Int,n: Int, d: Int): Fraction = new Fraction(x,n, d)
  def unapply(arg: Fraction): Option[(Int, Int)] = if(arg.den == 0) None else Some((arg.num,arg.den))
}

//使用
val a1 = new Fraction(3,4)
val a2 = new Fraction(2,4,2)
val Fraction(a,b) = a1*a2
println(s"a = ${a} , b = ${b}")
//a = 24 , b = 8

示例

object Name {
  def unapply(arg: String): Option[(String,String)] = {
    val pos = arg.indexOf(" ")
    if(pos == -1) None else{
      Some (arg.substring(0,pos),arg.substring(pos+1))
    }
  }
}
//
scala> val Name(a,b)="Cay Horstmann"
a: String = Cay
b: String = Horstmann

带单个参数或无参数的提取器

  • 如果unapply方法提取单值,应该返回一个目标类型的Option
object Number{
  def unapply(input:String): Option[Int] =
    try{
      Some(input.trim.toInt)
    }catch{
      case ex:NumberFormatException => None
    }
}
//val是修饰a的
scala> val Number(a)="231"
a: Int = 231
  • 提取器也可以只测试输入,不提取值,unapply方法返回个Boolean类型

unapplySeq方法

  • 提取任意长度的字符序列,使用unapplySeq来命名方法
  • 不要同时提供相同入参的unapply和unapplySeq方法
object Name {
  def unapplySeq(arg:String): Option[Seq[String]] ={
    if(arg.trim == "") None else{
      Some(arg.trim.split("\\s+"))
    }
  }
}

//
val author = "Cay Horstmann haha"
author match{
  case Name(first,last)=>println(first+"-"+last)
  case Name(first,last,m)=>println(first+"-"+last+";"+m)
  case _ => None
}
发布了57 篇原创文章 · 获赞 73 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/weixin_40450867/article/details/103569486
今日推荐