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") } }

最後,又定義了一個函數:

 

 


 
def biophony[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

 

“>:”符號

 

 

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

 


 
def biophony[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處理!

更多精彩內容,請關注我的微信公衆賬號 互聯網技術窩

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章