我正在尝试实现一个Scala特性来处理与需要我们创建的Java库连接的细节
我想做的是:
trait SomeTrait[A] extends JavaAPI {
def foo = {
callApi(classOf[A])
}
override def bar = {
foo
}
}
请注意,bar实际上是覆盖了基类中的方法,所以我无法更改它的签名。
我已尝试使用Manifest等几种变体,但无法完成此工作。有没有办法获取参数化类型的运行时类?
答案 0 :(得分:10)
这种味道可以解决问题:
trait SomeTrait[A] {
def foo(implicit ev: Manifest[A]) = {
callApi(ev.erasure)
}
}
更新在某些时候,必须通过方法参数注入清单。如果特征可以拥有它们,那么构造函数将是一个不错的选择。
实际上,他们可以!该特征具有与其混合的任何构造函数,因此如果您指定一个抽象清单,派生类必须定义...
trait SomeTrait {
def ev: Manifest[_] //abstract
def foo = println(ev.erasure)
}
//this `ev` provides the implementation, note that it MUST be a val, or var
class Concrete[T](implicit val ev: Manifest[T]) extends SomeTrait
一切都很好。
答案 1 :(得分:5)
你必须以某种方式得到清单,而且traits没有构造函数参数。只有你可以说出你想做的权衡。这是另一个。
trait SomeTrait[A] {
implicit def manifesto: Manifest[A]
def foo = println(manifest[A].erasure)
}
object SomeTrait {
def apply[A: Manifest] : SomeTrait[A] = new SomeTrait[A] { def manifesto = manifest[A] }
}
答案 2 :(得分:4)
由于类型擦除,编译器无法确定特征中的类型。因此,你想要的是无法做到的。但是,你可以把它变成一个类。这样,编译器可以在创建实例时传递证据参数。
class SomeTrait[A](implicit ev: Manifest[A]) extends JavaApi {
def foo = {
callApi(ev.erasure)
}
override def bar = {
foo
}
}
答案 3 :(得分:0)
在您的代码中执行此操作可能有点不方便,但您可以执行此操作
trait SomeTrait[A] extends JavaAPI {
def objType: Class[A]
def foo = {
callApi(objType)
}
override def bar = {
foo
}
}
object SomeImplementation with SomeTrait[SomeObject] {
val objType: Class[SomeObject] = classOf[SomeObject]
}
我知道这有点罗嗦,但这就是我解决这个问题的方法。我希望将来找到更好的解决方案,但这就是我现在正在使用的。如果有帮助,请告诉我。