简体   繁体   中英

How do I create an instance of a trait in a generic method in scala?

I'm trying to create an instance of a trait using this method

val inst = new Object with MyTrait

This works well, but I'd like to move this creation in to a generator function, ie.

object Creator {
  def create[T] : T = new Object with T
}

I'm obviously going to need the manifest to somehow fix the type erasure problems, but before I get to this, I run in to 2 questions :

  1. Even with an implicit manifest, Scala still demands that T be a trait. How do I add a restriction to create[T] so that T is a trait?

  2. If I chose to use the Class.newInstance method to create the instance dynamically rather than using "new", how would I specify the "with" in "new Object with T"? Is it possible to dynamically create new concrete mixin types at runtime?

I'm not sure what the motivation is for your question, but you could consider passing a factory for T as an implicit parameter. This is known as using type classes or ad-hoc polymorphism .

object Test extends Application {
  trait Factory[T] {
    def apply: T
  }
  object Factory {
    /**
     * Construct a factory for type `T` that creates a new instance by
     * invoking the by-name parameter `t`
     */
    def apply[T](t: => T): Factory[T] = new Factory[T] {
      def apply = t
    }
  }

  // define a few traits...
  trait T1
  trait T2

  // ...and corresponding instances of the `Factory` type class.
  implicit val T1Factory: Factory[T1] = Factory(new T1{})
  implicit val T2Factory: Factory[T2] = Factory(new T2{})

  // Use a context bound to restrict type parameter T
  // by requiring an implicit parameter of type `Factory[T]`
  def create[T: Factory]: T = implicitly[Factory[T]].apply

  create[T1]
  create[T2]

}

At the other end of the spectrum, you could invoke the compiler at runtime, as detailed in this answer to the question "Dynamic mixin in Scala - is it possible?".

You can't do this (even with a Manifest). The code new Object with T involves creating a new anonymous class representing the combination of Object with T . To pass this to your create function, you would have to generate this new class (with new bytecode) at runtime, and Scala has no facilities for generating a new class at runtime.

One strategy might be to try to transfer the special functionality of the factory method into the class's constructor instead, and then use the constructor directly.

Another possible strategy is to create conversion functions (implicit or otherwise) to the traits you're interested in using with this class.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM