无法获取列表中通用对象的类型 [英] Cannot get type of generic object in a list

查看:66
本文介绍了无法获取列表中通用对象的类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我具有以下特征:

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆