斯卡拉。使类通用

时间:2016-04-04 15:17:21

标签: scala generics

我有这个代码在我的项目中反复出现,我们为每个类型的序列化到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

1 个答案:

答案 0 :(得分:2)

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

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[_]]))
  }
}