2015-06-18 69 views
3

我有幾個對象,我正在嘗試編寫工廠方法。斯卡拉工廠方法與仿製藥

簡化,它們是:

case class a[a1,a2](j:a1, k:a2) {} 
case class b[b1,b2](j:b1, k:b2) {} 

我想創造條件,允許我在類型傳遞的方法,並獲得該類的實例。我試圖讓這樣的事情:

class myfactory[T] { 
    def make[K,L](p1: K, p2: L): T[K,L] = { 
    new T(p1,p2) 
    } 
} 

這顯然是行不通的(因各種原因,包括「T不能帶參數」),但有建立這樣的一個優雅的解決方案?

回答

5

0 __的答案几乎就在那裏。如果你使Factory[A[_,_]]是一個typeclass,你就全都設置好了。下面是名稱的示例規範:

// enable higher kinded types to prevent warnings 
import scala.language.higherKinds 

// our case classes 
case class A[A1,A2](j:A1, k:A2) 
case class B[B1,B2](j:B1, k:B2) 

// Define our factory interface 
trait Factory[T[_,_]] { 
    def make[P1,P2](p1: P1, p2: P2): T[P1,P2] 
} 

// Companion class makes factory easier to use 
object Factory { 
    def apply[T[_, _]](implicit ev: Factory[T]) = ev 
} 

// Add implicit implementations of Factory[A] 
implicit object AFactory extends Factory[A] { 
    def make[P1,P2](p1: P1, p2: P2): A[P1,P2] = A(p1, p2) 
} 

// Add implicit implementations of Factory[B] 
implicit object BFactory extends Factory[B] { 
    def make[P1,P2](p1: P1, p2: P2): B[P1,P2] = B(p1, p2) 
} 

現在測試試驗工廠在RE​​PL

scala> val a = Factory[A].make("one", 2) 
a: A[String,Int] = A(one,2) 

scala> val b = Factory[B].make(1, "two") 
b: B[Int,String] = B(1,two) 
2

new關鍵字cannot與類型參數一起使用,只能用於具體類,因爲在編譯時檢查實例化。您可以使用reflection解決此問題。

可能更好的方法是提供特定的工廠。

E.g.

trait Factory[A[_,_]] { 
    def make[P, Q](p: P, q: Q): A[P, Q] 
} 

case class a[a1,a2](j:a1, k:a2) {} 

object AFactory extends Factory[a] { 
    def make[P, Q](p: P, q: Q): a[P, Q] = a(p, q) 
}