Scala factory method with generics

I have several objects for which I am trying to write a factory method.

Simplified:

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

      

I would like to create a method that would allow me to pass a type and get an instance of this class. I am trying to find something like this:

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

      

This clearly does not work (for various reasons, including "T cannot take parameters"), but is there an elegant solution to create something like this?

+3


source to share


2 answers


0__ the answer is almost there. If you make a Factory[A[_,_]]

class, you're all set. Here's an example with standardized names:

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

      



Now test the factory test in the REPL

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)

      

+5


source


The keyword new

cannot be used with a type parameter, only a specific class, as the object instance is checked at compile time. You can get around this with reflection .

Probably the best approach is to provide specific factories.



eg.

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

      

+2


source







All Articles