Reputation: 2320
I'm trying to use generics in Scala but in some case it doesn't work to me.
I have define a class as:
trait Generic[T <: Product] extends Serializable {
def start(ssc: StreamingContext, conf: Conf) = {
val dstream = createDirectStream(...)
val rdd = dstream.map(x => avroToObject(x.value()))
execute(rdd)
}
def execute(dstreamAvro: DStream[T]): Unit
def avroToObject(bytes: Array[Byte]): T
}
Later, I implement the avroToObject method in a specific class. When I try to compile the code I get an error.
Error:(36, 30) No ClassTag available for T
val rddAvro = dstream.map(x => avroToObject(x.value()))
Error:(36, 30) not enough arguments for method map: (implicit evidence$2: scala.reflect.ClassTag[T])org.apache.spark.streaming.dstream.DStream[T].
Unspecified value parameter evidence$2.
val rddAvro = dstream.map(x => avroToObject(x.value()))
What is it happening? How could I fix it?
If I changed the declaration of the class by:
abstract class Generic[T <: Product](implicit c: ClassTag[T]) extends Serializable {..
It works, but I don't understand why, and why it's neccesary that implicit.
Upvotes: 3
Views: 2141
Reputation: 149518
What is it happening? How could I fix it?
What is happening is that one of the methods down the execution chain requires an instance of ClassTag[T]
to be present. Although we don't have the implementation here, I'm assuming that is the KafkaUtils.createDirectStream
method which needs information of type T
at run time.
This works:
abstract class Generic[T <: Product](implicit c: ClassTag[T])
Because now that implicit is in scope when you call createDirectStream
. That is, the compiler is the one which fills in the relevant class tag at compile time for you, and now createDirectStream
has the relevant implicit in scope to use.
Upvotes: 6