无法获取列表中通用对象的类型 [英] Cannot get type of generic object in a list
问题描述
我具有以下特征:
trait Storage[C <: Config] {
def get(name: String, version: Int): Option[C]
def list: List[(String, String)]
def register(config: C): Boolean
}
我想创建以下类:
class MultiStorage[C <: Config](storages: List[Storage[_ <: C]]) extends Storage[C] {
def get(name: String, version: Int): Option[C] = {...}
def list: List[(String, String)] = {...}
def register(config: C) = {...}
如果不清楚,其含义是MultiStorage
将类型为C
(或子类型)的元素存储在多个存储中,每个存储中都包含单个类型的元素.
If not clear, the meaning is that a MultiStorage
stores elements of type C
(or subtype) in several storages, each of them containing elements of a single type.
我正在与泛型作斗争以实现register方法.这个想法是,根据我要注册的对象的类型,我需要选择合适的存储空间进行注册,例如:
I am fighting with generics to implement the register method. The idea is that depending on the type of object I want to register, I need to choose the right storage to register on, something like:
def register(config: C) = {
storages.foreach(s => {
if (typeOf(s) is Storage[C]) { // same type of config
s.register(config)
return
}
})
}
我尝试了一些泛型和类型标记,但是在这里没有什么有用的分享.我可能想我需要添加另一个类型标签,以区分我在寄存器中收到的内容和声明为存储类型的内容.
I made several attempts with generics and type tags, however nothing useful to share here. I am probably thinking I need to add another type tag to distinguish what I receive in register and what is declared as type of the storage.
我尝试过的想法之一是在Storage
中有一个返回类型的方法:
One of the ideas I tried was having a method in Storage
that returns the type:
protected def getType()(implicit tag: TypeTag[C]): universe.Type = typeOf[C]
但是在呼叫方,我可以得到类似_$1
这样的结果,老实说我不明白这是什么意思.
but on the caller side I was able to get as result something like _$1
, which I honestly don't understand what it means.
另一种尝试是使用shapeless
,但是在这种情况下,我不确定在HList
存储中是否可以有一个包含任意数量元素的多存储
Another try was to use shapeless
, but in this case I am not sure if it is possible having a multi-storage containing an arbitrary number of elements in an HList
storage
推荐答案
需要使运行时类可用,例如:
The runtime class needs to be made available, for example:
class Config
class FooConfig extends Config
class BarConfig extends Config
trait Storage[C <: Config] {
val ctag: ClassTag[C]
def get(name: String, version: Int): Option[C]
def list: List[(String, String)]
def register(config: C): Boolean
}
class FooStorage(implicit val ctag: ClassTag[FooConfig]) extends Storage[FooConfig] {
override def get(name: String, version: Int): Option[FooConfig] = ???
override def list: List[(String, String)] = ???
override def register(config: FooConfig): Boolean = ???
}
class BarStorage(implicit val ctag: ClassTag[BarConfig]) extends Storage[BarConfig] {
override def get(name: String, version: Int): Option[BarConfig] = ???
override def list: List[(String, String)] = ???
override def register(config: BarConfig): Boolean = ???
}
class MultiStorage[C <: Config](storages: List[Storage[_ <: C]])(implicit val ctag: ClassTag[C]) extends Storage[C] {
def get(name: String, version: Int): Option[C] = ???
def list: List[(String, String)] = ???
def register(config: C): Boolean = {
storages.foreach(storage => {
if (storage.ctag.runtimeClass.isAssignableFrom(config.getClass)) {
}
})
???
}
}
由于特征不能具有构造函数参数,因此在实现该特征的每个类中都需要重复使用隐式类标记.如果您的类结构允许Storage
成为抽象类,则可以减少样板数量:
As traits can't have constructor parameters, the implicit class tag needs to be repeated in every class implementing the trait. If your class structure allows Storage
to be an abstract class instead, the amount of boilerplate can be reduced:
abstract class Storage[C <: Config](implicit val ctag: ClassTag[C]) {
def get(name: String, version: Int): Option[C]
def list: List[(String, String)]
def register(config: C): Boolean
}
class FooStorage extends Storage[FooConfig] {
override def get(name: String, version: Int): Option[FooConfig] = ???
override def list: List[(String, String)] = ???
override def register(config: FooConfig): Boolean = ???
}
这篇关于无法获取列表中通用对象的类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!