2015-02-12 59 views
0

我有一個特徵定義了一個函數 - 我不想指定它將如何工作,直到以後。這個特點是混在幾個班的情況下,像這樣:在scala中使用值類來實現特徵方法?

trait AnItem 
trait DataFormatable { 
    def render():String = "" // dummy implementation 
} 
case class Person(name:String, age:Int) extends DataFormatable with AnItem 
case class Building(numFloors:Int) extends DataFormatable with AnItem 

好了,現在我想的是拉皮條的這種渲染行爲的具體實現方式可包含的模塊。想在這裏使用值類:

object JSON { 
    implicit class PersonRender(val p:Person) extends AnyVal { 
    def render():String = { 
     //render json 
    } 
    } 
    // others 
} 

object XML { 
    implicit class PersonRender(val p:Person) extends AnyVal { 
    def render():String = { 
     //render xml 
    } 
    } 
    // others 
} 

理想的使用應該是這樣的(假設所需JSON輸出):

import JSON._ 
val p:AnItem = Person("John",24) 
println(p.render()) 

所有很酷 - 但它不工作。有沒有一種方法可以讓這個可裝載的實現工作起作用?我關門了嗎?

回答

0

DataFormatable特質在這裏什麼也沒有做,只是讓你回不去。你應該擺脫它。由於您想根據範圍內存在的隱含實現render實現,因此Person不能有有自己的render方法。如果Person首先沒有名爲render的方法,編譯器將僅查找隱式轉換爲PersonRender。但是因爲PersonDataFormatable繼承(或被迫執行)render,所以不需要尋找隱式轉換。

根據您的編輯,如果您有一個List[AnItem]的集合,也不可能將元素隱式轉換爲具有render。雖然每個子類都可能有一個隱式轉換,但它們會給予它們render,編譯器不知道它們何時全部堆積到更抽象類型的列表中。特別是一個空的特質,如AnItem

您如何完成這項工作?你有兩個簡單的選項。

一,如果你想堅持隱式轉換,你需要刪除DataFormatable作爲你的案例類的超類型,以便它們沒有自己的render方法。然後你可以換出XML._JSON._,轉換應該可以工作。但是,你不會被允許混合收藏。

二,完全放棄了implicits,有你的特點是這樣的:

trait DataFormatable { 
    def toXML: String 
    def toJSON: String 
} 

這樣,你強迫每一個在DataFormatable混合包含序列化信息(這是它應該是這樣的類,而比隱藏它們隱含)。現在,當您有List[DataFormatable]時,您可以證明所有元素都可以轉換爲JSON或XML,因此您可以轉換混合列表。我認爲這會更好,因爲代碼應該更直接。你有什麼進口產品不應該確定後續行爲。想象一下可能會出現的混淆,因爲XML._已被導入到文件的頂部而不是JSON._

+0

我想我明白了。所以我更新了我的例子。如果我有一組具有不同實現的對象(特徵)(比如上面的AnItem列表),我想將它們呈現爲JSON或XML,具體取決於。如果它們中沒有一個實現render(),那麼在修改的示例中對特徵(AnItem)進行操作時,編譯器如何找到render()? – Greg 2015-02-12 03:51:05

+0

它不能基於'AnItem'的類型信息。要麼編譯器需要知道你有'Person',所以它可以找到正確的隱式,或者'Person'(和其他類型)可能應該從一個共同的特性實現諸如toJSON和toXML等方法。這取決於你想要走哪條路。 – 2015-02-12 04:01:24

+0

@Greg看我的編輯。 – 2015-02-12 11:59:10

相關問題