2013-02-25 2 views
1

У меня есть следующий код, написанный на Scala 2.10.0:Возможно ли создать экземпляр класса, переданного как параметр в общий признак в Scala?

trait A[T <: B] { 
    self : { def foo() } => 

    val action :()=>Unit = this.foo _ 
    //wanna make default for this 
    val construction : String=>T 

    def bar()(implicit x : String) : T = { 
    action() 
    val destination = construction(x) 
    destination.baz() 
    destination 
    } 
} 

trait B { def baz() {} } 

class Xlass { def foo() {} } 

class Klass(a : String)(implicit val x : String) extends B { 
    val f = new Xlass with A[Klass] { 
     //boilerplate! 
     val construction = new Klass(_) 
    } 
} 

implicit val x = "Something" 
val destination = new Klass("some a").f.bar() 

Интересно, можно ли сделать по умолчанию для construction, таких как val construction = new T(_)? На данный момент я пробовал несколько вариантов, но ни один из них не работает со всеми характеристиками этого кода, такими как использование ограничений типа, неявки и структурной типизации. Насколько я мог бы получить это, но он терпит неудачу с scala.ScalaReflectionException: free type T is not a class:

import reflect.runtime.universe._ 
val tT = weakTypeTag[T] 
... 
val privConstruction = 
    x : String => 
    runtimeMirror(tT.mirror.getClass.getClassLoader) 
    //fails here with scala.ScalaReflectionException: free type T is not a class 
    .reflectClass(tT.tpe.typeSymbol.asClass) 
    .reflectConstructor(tT.tpe.members.head.asMethod)(x).asInstanceOf[T] 
+1

Что такое Tt? Предоставьте полный фрагмент. –

+0

@EugeneBurmako Fixed :) – Lakret

+0

T вот только параметр типа, о котором Scala ничего не знает. Это то, на что намекает рефлексия. Чтобы распространять информацию о Т от сайтов вызовов до вызываемых лиц, вам необходимо аннотировать Т с привязкой к типу TypeTag или WeakTypeTag, как в 'class C [T: TypeTag]'. К сожалению, границы контекста не поддерживаются для признаков, поэтому вам придется работать. –

ответ

1

Итак, в конце концов, я сделал это:

trait A[T <: B] { 
    self : { def foo() } => 

    val action :()=>Unit = this.foo _ 
    def construction(x: String)(implicit tag : reflect.ClassTag[T]) : T = { 
    tag.runtimeClass.getConstructor(classOf[String], classOf[String]).newInstance(x, x).asInstanceOf[T] 
    } 

    def bar()(implicit x : String, tag : reflect.ClassTag[T]) : T = { 
    action() 
    val destination = construction(x) 
    destination.baz() 
    destination 
    } 
} 

trait B { def baz() {} } 

class Xlass { def foo() {} } 

class Klass(a : String)(implicit val x : String) extends B { 
    val f = new Xlass with A[Klass] 
} 

implicit val x = "Something" 
val destination = new Klass("some a").f.bar()