在scala中创建类型的新实例

在scala中创建类型的新实例,scala,types,Scala,Types,如果我有一个C类定义为 class C[A] 有没有办法在C中创建a的新实例?差不多 class C[A] { def f(): A = new A() } 我理解,如果这是可能的,您可能必须在某个地方指定构造函数参数,这很好 如果不可能,是否有任何设计模式用于处理您希望创建类型的新实例的情况?您可以使用类型类来抽象实例化: trait Makeable[T] { def make: T } class C[T: Makeable] { def f(): T = impli

如果我有一个C类定义为

class C[A]
有没有办法在C中创建
a
的新实例?差不多

class C[A] {
  def f(): A = new A()
}
我理解,如果这是可能的,您可能必须在某个地方指定构造函数参数,这很好


如果不可能,是否有任何设计模式用于处理您希望创建类型的新实例的情况?

您可以使用类型类来抽象实例化:

trait Makeable[T] {
   def make: T
}

class C[T: Makeable] {
   def f(): T = implicitly[Makeable[T]].make
}
比如说,

implicit object StringIsMakeable extends Makeable[String] {
   def make: String = "a string"
}

val c = new C[String]
c.f // == "a string"
当您实例化C时,您需要显式或隐式地提供一个Makeable,它将充当适当类型的工厂。当然,该工厂将负责在调用构造函数时提供任何构造函数参数

或者,您可以使用清单,但请注意,此方法依赖于反射,并且不是类型安全的:

class C[T: Manifest] {
   def f(): T = manifest[T].erasure.newInstance.asInstanceOf[T]
}
为了完整性,您还可以轻松地扩展此方法,将部分或全部构造函数参数传递给make方法:

trait Makeable[Args, T] { def make(a: Args): T }

class C[Args, T](implicit e: Makeable[Args, T]) {
   def f(a: Args): T = e.make(a)
}

// some examples
case class Person(firstName: String, lastName: String)

implicit val personFactory1 = new Makeable[(String, String), Person] {
   def make(a: (String, String)): Person = Person(a._1, a._2)
}
implicit val personFactory2 = new Makeable[String, Person] {
   def make(a: String): Person = Person(a, "Smith")
}

val c1 = new C[String, Person]
c1.f("Joe") // returns Person("Joe", "Smith")

val c2 = new C[(String, String), Person]
c2.f("John", "Smith") // returns Person("John", "Smith")

您可以要求隐式参数,如下所示:

class A[T](implicit newT : T) { 
  val t = newT 
} 
然后,当实例化
A
时,只需在作用域中具有所需类型的隐式工厂,例如,以下工作:

implicit def newSeq[T] = Seq[T]()                
val a = new A[Seq[String]]                            
如图所示:

scala> a.t
res22: Seq[String] = List()

与@Raphael对案例类的
apply
方法的回答相同:

class Container[A](contained: A)
case class Person(name: String)
case class PersonContainer(person: Person) extends Container[Person](person)
implicit def _ = PersonContainer.apply _

class Creator {
  def deserializeAndPackage[A, B <: Container[A]](data: Array[Byte])
                           (implicit containerCreator: (A => B)): B = {
    val p = /* deserialize data as type of A */
    containerCreator(p)
  }
}
类容器[A](包含:A)
案例类人员(名称:字符串)
案例类PersonContainer(person:person)扩展容器[person](person)
隐式定义=PersonContainer.apply_
类创建者{
def反序列化和包[A,B]:B={
val p=/*将数据反序列化为*/
集装箱装卸工(p)
}
}

如果具体类型没有(无参数)构造函数,您建议怎么办?理想情况下,您可以在类型参数中指定它。因此我可以将C定义为
类C[a(字符串,字符串)]
或其他什么。然后我必须用两个字符串参数调用a。@Raphael否,但
类C[(字符串,字符串),a]
可能是。通过使用第二个类型参数,扩展我下面的方法,将一些(或全部)构造函数参数传递到
make
方法中,这是非常简单的。但是,C的一个定义只适用于一个特定的构造函数签名。这是我的观点。@Raphael不是这样。
C类[Args,T](隐式e:Makeable[Args,T]){…}
。每个Makeable实例将根据需要对Args类型进行分解,以调用正确的构造函数。