1. 程式人生 > >Scala 的那些奇怪的符號 (一):“:” 作用及用法

Scala 的那些奇怪的符號 (一):“:” 作用及用法

    Scala的語法很多,有些人認為過於繁瑣,有些人卻認為正是因為繁瑣,所以才讓這門語言嚴謹和強大。

   例如在翻閱Scala資料或者檢視Scala原始碼的時候,經常會看到“<:”和“>:”,這是什麼鬼?下面我就來探討一下這兩個符號的用法:

“<:”符號

我們定義一個類:“Earth”

class Earth {
  def sound(){
    println("hello !")
  }
}

我們定義了一個子類:“Animal”

class Animal extends Earth{
  override def sound() ={
    println
("animal sound") } }
然後 ,還有Animal 的一個子類 “Bird”
class Bird extends Animal{
  override def sound()={
    print("bird sounds")
  }
}
最後,又定義了一個函式:
defbiophony[T <: Animal](things: Seq[T]) = things map (_.sound)

乍一看:這tm是什麼鬼?“<:”是什麼意思?

其實, 這屬於Scala泛型中的知識:上邊界和下邊界。上邊界是“<:”,下邊界是“>:”;T <: Animal的意思是:T必須是Animal的子類。這樣一來,我們再看看這個函式的意思:定義了一個叫“biophony”的函式,這個函式的引數必須傳一個集合,一個什麼樣的集合呢?Animal 子類或者是Animal的集合(包含Animal)。函式右邊就很好理解了,map中每個元素呼叫了sound方法。

知道了是什麼之後,接著呼叫就很簡單了:

  biophony(Seq(new Bird, new Bird))

這樣一來就輸出:

bird sounds
bird sounds

完美!

假如因為可以包含Animal所以,這麼呼叫也可以:

   biophony(Seq(new Animal, new Animal))
輸出:

animal sound
animal sound

甚至可以一個Animal,一個Bird,多型嘛!

  biophony(Seq(new Animal, new Bird))

輸出:

animal sound
bird sounds

但是,這樣就不可以了:

  biophony(Seq(new Earth, new Earth))
輸出:

報錯!

Scala的定義了一個“界限”來規定泛型可以適用的在繼承關係中的範圍,“<:”是上限,表示不超過XXX

“>:”符號

我們把“<:”換成了“>:”

  defbiophony[T >: Animal](things: Seq[T]) = things map (_.sound())
不對這怎麼還報紅了呢?細細想來,Animal的父類的話,不能確定能不能有sound()方法呀,因為父類太多了,Object還是呢。報錯也正常,我們就直接返回 things吧
  def biophony[T >: Animal](things: Seq[T]) = things 
好了,這下好了,不報紅了,我們傳一個Animal的父類“Earth”的佇列,然後沒個元素呼叫“sound()”方法
  biophony(Seq(new Earth, new Earth)).map(_.sound())
輸出:

hello !
hello !

之前的結論,呼叫Animal也應該是可以的:

  biophony(Seq(new Animal, new Animal)).map(_.sound())

輸出:

animal sound
animal sound

好的,也是正確的。假如我們傳Animal子類Bird看看會不會報錯

  biophony(Seq(new Bird, new Bird)).map(_.sound())
輸出:

bird sounds
bird sounds

居然不報錯!還運行了!這是怎麼回事??

我們看一下傳Bird後的返回值是什麼:


是Animal !真相大白了,由於Bird是子類,Scala把Bird當做Animal來處理了。也就是說,“>:”的時候,傳任何引數都可以,但是返回值回有所不同,Animal的子類都會統一按照Animal來處理!

那我們傳一個和Animal毫不相關的類,會出現什麼情況呢?

class Moon {

}

寫了一個Moon,然後按照如下文傳參呼叫

  biophony(Seq(new Moon, new Moon))
不報錯!

我們看一下返回值:


Object!Scala把它看做了Object。也就是說,可以隨便傳!只不過和Animal直系的,是Animal父類的還是父類處理,是Animal子類的按照Animal處理,和Animal無關的,一律按照Object處理!