2013-07-20 96 views
1

我有一個迭代器,我希望允許客戶端以不同類型進行格式化。例如,我想要有一個如下界面:將數據轉換爲多種類型之一的設計模式[斯卡拉]

val results = new Results[Integer](Seq(1,2,3,4)) 
results.foreach(print)  // Prints 1, 2, 3, 4 

val jsResults = results.as[JsArray] 
jsResults.foreach(print) // Prints [ [1], [2], [3], [4] ] 

results.as[String].foreach(print) // Prints "1", "2", "3", "4" 
results.as[HTML].foreach(print) // Prints <tr><td>1</td><td>2</td>...</tr> 

什麼是優雅的類設計來實現這個?我採取的方法是一個抽象結果類與每個結果類型的子類。因此,像:

abstract class Results[T](...) 
class JsonResults extends Results[JsArray] 
class StringResults extends Results[String] 
class HTMLResults extends Results[HTML] 

但我在實施上abstract class Results一個函數返回給定的結果類型的正確子類的麻煩。這是我到目前爲止,但我發現所有類型的編譯錯誤:

abstract class Results[T](...) { 
    def as[A : ClassTag]: Result[A] = implicitly[ClassTag[A]] = { 
     case implicitly[ClassTag[JsArray]] => new JsonResults(...) 
     ... 
    } 
} 

錯誤的樣子:

[error] found : JsonResults 
[error] required: Result[A] 
[error]  case implicitly[ClassTag[JsArray]] => new JsonResults(...) 

讓我知道如果有什麼我可以澄清。

+1

鏈接的例子,我不知道你想要完成的任務。你只是想要不同的方式來格式化結果?如果是這樣,一些簡單的方法需要一個結果[T]並返回一個字符串有什麼問題?或者您是否想要定義可以使用方法訪問的隱式轉換,使其不像真實的隱式轉換那麼危險? –

+0

編譯器不夠聰明,隱式['ClassTag [JsArray]]'意味着'A'是'JsArray',所以它不能知道'JsonResults'是'Result [A]',因此錯誤。但是你知道它是這樣的,所以你可以用手施展...... – gourlaysama

+0

這幾乎肯定是沒有實際目的的過度複雜化。解決這個問題肯定會導致性能開銷,因爲逃避反射。只需使用簡單的方法,如'asJSON'或'asString'。 –

回答

0

您正朝着正確的方向使用含義構造類型類。

你可以在優秀的sjson庫中看到示例。

鑑於示例參數化在類型從其中執行轉換。你應該在目標類型添加第二個參數化:

trait Writes[T, R] { 
    def writes(o: T): R 
} 

def serialize[T,R](o: T)(implicit wrt: Writes[T,R]): R = wrt.writes(o) 

而且你應該寫的實現,根據協議,在上面

相關問題