在scala中创建类型的新实例

Aar*_*ken 9 types scala

如果我将C类定义为

class C[A]
Run Code Online (Sandbox Code Playgroud)

有没有办法A在C中创建一个新的实例?就像是

class C[A] {
  def f(): A = new A()
}
Run Code Online (Sandbox Code Playgroud)

我明白,如果这是可能的,你可能必须在某处指定构造函数参数,这很好.

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

Aar*_*rup 10

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

trait Makeable[T] {
   def make: T
}

class C[T: Makeable] {
   def f(): T = implicitly[Makeable[T]].make
}
Run Code Online (Sandbox Code Playgroud)

例如,

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

val c = new C[String]
c.f // == "a string"
Run Code Online (Sandbox Code Playgroud)

当您实例化C时,您需要显式或隐式地提供一个Makeable,它将充当适当类型的工厂.当然,该工厂负责在调用构造函数时提供任何构造函数参数.

或者,您可以使用Manifest,但要注意这种方法依赖于反射并且不是类型安全的:

class C[T: Manifest] {
   def f(): T = manifest[T].erasure.newInstance.asInstanceOf[T]
}
Run Code Online (Sandbox Code Playgroud)

为了完整起见,您还可以轻松扩展此方法,将部分或全部构造函数参数传递给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")
Run Code Online (Sandbox Code Playgroud)


Rap*_*ael 5

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

class A[T](implicit newT : T) { 
  val t = newT 
} 
Run Code Online (Sandbox Code Playgroud)

您需要的只是在实例化时在范围内拥有所需类型的隐式工厂A,例如以下工作:

implicit def newSeq[T] = Seq[T]()                
val a = new A[Seq[String]]                            
Run Code Online (Sandbox Code Playgroud)

如图所示:

scala> a.t
res22: Seq[String] = List()
Run Code Online (Sandbox Code Playgroud)