2010-07-18 3 views
6

Я пытаюсь создать экземпляр признака с помощью этого методаКак создать экземпляр признака в общем методе в scala?

val inst = new Object with MyTrait 

Это хорошо работает, но я хотел бы, чтобы переместить это творение, чтобы функции генератора, то есть.

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

Я, очевидно, буду нуждаться в манифесте, чтобы как-то исправить проблемы типа стирания, но прежде, чем я доберусь до этого, я бег на 2 вопрос:

  1. Даже с неявным манифестом , Scala все еще требует, чтобы T был признаком. Как добавить ограничение для создания [T], чтобы T был признаком?

  2. Если я решил использовать метод Class.newInstance для создания экземпляра динамически, а не с помощью «нового», как бы указать «с» в «новом объекте с T»? Можно ли динамически создавать новые типы бетонных смесей во время выполнения?

ответ

8

Вы не можете этого сделать (даже с манифестом). Код new Object with T предполагает создание нового анонимного класса, представляющего комбинацию Object with T. Чтобы передать это функции create, вам придется сгенерировать этот новый класс (с новым байтовым кодом) во время выполнения, а у Scala нет возможностей для создания нового класса во время выполнения.

Одна из стратегий может заключаться в том, чтобы попытаться перенести специальную функциональность фабричного метода в конструктор класса вместо этого, а затем использовать конструктор напрямую.

Другой возможной стратегией является создание функций преобразования (неявных или иных) для характеристик, которые вы заинтересованы в использовании этого класса.

+0

Это, кажется, интересное ограничение языка, но я не вижу причины, почему его нельзя было установить с помощью новой поддержки динамического микширования в Scala. Код признака уже доступен как статические методы, поэтому поиск в линеаризации может быть вычислен во время выполнения, а не запечен в байт-коде класса. Тогда вам просто нужно добавить проверку типа времени выполнения, так что «asInstanceOf» работает. – ACyclic

14

Я не уверен, какова мотивация вашего вопроса, но вы можете рассмотреть возможность передачи фабрики для T в качестве неявного параметра. Это известно как использование классов или ad-hoc полиморфизм.

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] 

} 

На другом конце спектра, вы можете вызвать компилятор во время выполнения, как описано в this answer на вопрос «Dynamic подмешать в Scala - это возможно».

+0

Спасибо, мне, возможно, придется использовать этот метод. Моим вариантом использования является Java-прокси. Я хочу написать библиотеку, которая является удаленной. Поэтому мне нужно определить интерфейсы для всех моих классов, что является болью, поскольку я хочу разоблачить все. Одно из решений - написать все как черту, затем я бесплатно получу определение интерфейса. Целью функции create является создание экземпляра на «конкретной» стороне прокси-соединения. – ACyclic