【问题标题】:Scala. Making a class generic斯卡拉。使类泛型
【发布时间】:2016-04-04 23:32:58
【问题描述】:

对于我们序列化为 Avro 的每种类型的类,我的项目中反复出现此代码

class FooKryoRegistrator extends KryoRegistrator {
  override def registerClasses(kryo: Kryo) {
    kryo.register(classOf[Foo], SpecificRecordBinarySerializer(classTag[Foo]))    
    kryo.register(classOf[GenericData.Array[_]], new SpecificInstanceCollectionSerializer(classOf[java.util.ArrayList[_]]))
  }
}

现在,我不必为我项目中的每个实体(Foo、Bar、Baz .....)编写这个 Registrator 类,我认为让它通用化会更好。所以我做到了

class GenericKryoRegistrator[T] extends KryoRegistrator {
  override def registerClasses(kryo: Kryo) {
    kryo.register(classOf[T], SpecificRecordBinarySerializer(classTag[T]))    
    kryo.register(classOf[GenericData.Array[_]], new SpecificInstanceCollectionSerializer(classOf[java.util.ArrayList[_]]))
  }
}

但是我得到一个编译时错误

class type required but T found

我搜索了这个错误并发现了一个建议,我应该使用 ClassTag 而不是 class。所以我将实现更改为

class GenericKryoRegistrator[T] extends KryoRegistrator {
  override def registerClasses(kryo: Kryo) {
    kryo.register(classTag[T].runtimeClass, SpecificRecordBinarySerializer(classTag[T]))    
    kryo.register(classOf[GenericData.Array[_]], new SpecificInstanceCollectionSerializer(classOf[java.util.ArrayList[_]]))
  }
}

但现在它说

No ClassTag available for T

【问题讨论】:

    标签: scala generics


    【解决方案1】:

    如果您将类标签作为类的隐式参数,则可以使用它:

    class GenericKryoRegistrator[T] (implicit ct: ClassTag[T]) extends KryoRegistrator {
      override def registerClasses(kryo: Kryo) {
        kryo.register(ct.runtimeClass, SpecificRecordBinarySerializer(ct))
        kryo.register(classOf[GenericData.Array[_]], new SpecificInstanceCollectionSerializer(classOf[java.util.ArrayList[_]]))
      }
    }
    

    【讨论】:

    • 谢谢。那么调用者将如何实例化这个类呢?我们如何获得隐式的实际参数?
    • 我不确定机制,但我相信编译器会“自动”提供类标签
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-19
    • 2013-01-26
    • 2020-12-15
    • 2016-05-08
    • 2011-09-16
    • 1970-01-01
    • 2016-01-31
    相关资源
    最近更新 更多