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
}
發佈了75 篇原創文章 · 獲贊 83 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章