<%
這個符號有點像“<:”,但作用卻完全不一樣,類型上邊界“<:”的意思有點像繼承,A <: B 表示 A是B的子類;而A <% B的意思是“A可以轉化爲B”,這裏可以不必強調A和B本身的關係,只要有一個從A到B的隱士轉化即可。(注意:不必是隱士轉換,因爲可能是B類本身)下面我們看例子:
依然是上幾篇文章中的那幾個例子,有Earth、Anima、Bird三個類,三者之間的關係是:Bird繼承於Animal,Animal繼承於Earth
class Earth {
def sound(){
println("hello !")
}
}
class Animal extends Earth{
override def sound() ={
println("animal sound")
}
}
class Bird extends Animal{
override def sound()={
print("bird sounds")
}
}
然後我們定義一個函數:
def biophony[T <% Animal](things: T) = {
things.sound()
}
然後調用此方法:
biophony(new Earth)
輸出結果:
它說得要一個從Earth到Animal的隱士轉化,我們給它加上:
implicit def autoChange(things:Earth) = new Animal
運行:
成功!
我們講到 A <% B,A和B可以沒有父子關係,於是:
implicit def autoChange(things:String) = new Animal
def biophony[T <% Animal](things: T) = {
things.sound()
}
調用:
biophony(new String)
輸出:
成功!
A<%B 原來可以當B 直接用!和傳個B類型的參數沒有區別,那麼,我們真傳一個B,還用類型轉化嗎?咱們把類型轉化去掉。
def main(args: Array[String]) {
biophony(new Animal)
}
// implicit def autoChange(things:String) = new Animal
def biophony[T <% Animal](things: T) = {
things.sound()
}
運行,輸出:
看來,如果直接傳過需要轉化成的參數類型,就不必做類型轉化了。
A:B
上下文邊界。在這裏,不同於傳參的A:B,在這裏的意思是:必須存在一個“B[A]”的隱士值。
定義一個函數:
def biophony[T:Seq](things: T) = {
println("hello world")
}
如果直接調用:
def main(args: Array[String]) {
biophony(new Animal)
}
輸出:
缺少B[A]的隱士參數,我們給它加上一個,然後調用:
implicit val b = Seq(new Animal)
biophony(new Animal)
成功!
"A <% B"和“A:B”都是和隱士轉化有關,“A <% B”是有A到B的隱士轉化,“A:B”是有B[A]的隱士參數。