views:

371

answers:

2

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?

+7  A: 

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.

Ken Bloom
This seems to be an interesting limitation of the language, but I don't see a reason why it couldn't be fixed with a new "Dynamic" mixin support in Scala. The trait code is already available as static methods, so the linearization lookup could be computed at runtime rather than baked in to the class bytecode. Then you'd just need to add runtime type checking so "asInstanceOf" works.
NYCBrit
+11  A: 

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?".

retronym
Thanks, I may have to use this method.My use case is the Java Proxy. I want to write a library which is remotable. I therefore need to define interfaces for all my classes, which is a pain as I want to expose everything. One solution is to write everything as a trait, then I get the interface definition for free. The purpose of the create function is to instantiate a trait on the "concrete" side of the proxy connection.
NYCBrit