我有两种类型的数据:String和从SpecificRecordBase扩展,以及具有相同业务逻辑的几种方法来处理这些数据,除了使用我无法更改的另一个库中的java方法。
def createResultStreamSpecificRecordBase[T <: SpecificRecordBase](topic: String, source: DataStream[KafkaSourceType])(
implicit tag: ClassTag[T]): DataStream[T] = {
// contain calling java method with T <: SpecificRecordBase
serialize(source, topic)
// the same logic
}
def createResultStreamString(topic: String, source: DataStream[KafkaSourceType]): DataStream[String] = {
// dont contain calling java method with T <: SpecificRecordBase
// the same logic
}
def processSpecificRecordBase[T <: SpecificRecordBase](...)(implicit tag: ClassTag[T]): Unit = {
val stream = createStreamSpecificRecordBase(topic, source)
// the other the same process actions
}
def processString(...): Unit = {
val stream = createResultStreamString(topic, source)
// the other the same process actions
}
我想在处理方法中删除重复的代码,然后写一个。你能写一下怎么做吗?可以在泛型类型中使用类似OR的东西吗?
def process[T <: SpecificRecordBase ?OR? String](...)(implicit tag: ClassTag[T]): Unit = {
val stream = createStream(topic, source)
this match {
case SpecificRecordBaseRunner() => createStreamSpecificRecordBase(topic, source)
case StringRunner() => createStreamString(topic, source)
}
// the other process actions
}
答案 0 :(得分:1)
不幸的是,目前您没有所描述的OR
类型的运算符。好消息,Union Types
功能是即将推出的Dotty的一部分:
https://dotty.epfl.ch/docs/reference/new-types/union-types.html
现在,此类问题通常可以通过以下方法解决:
总和类型
您可以声明sealed trait
,该框将装箱所有可能的实例。
请查看下一个代码示例以获取更多详细信息:
// This is your base of sum type
sealed trait TopicResult
//Declared instances which you need to handle
case class RecordResult[T <: SpecificRecordBase](tag: ClassTag[T]) extends TopicResult
case object StringResult extends TopicResult
//Helper methods goes here for convenience
object TopicResult {
def record[T <: SpecificRecordBase](implicit tag: ClassTag[T]): TopicResult = RecordResult(tag)
def string: TopicResult = StringResult
}
def process(result: TopicResult /*other arguments*/): Unit = {
// This pattern matching should be safe, because you know all instances in advance.
result match {
case RecordResult(tag) => createStreamSpecificRecordBase(topic, source)
case StringResult => createStreamString(topic, source)
}
/// other operations
}
即席多态
也称为Type Class
模式。您可以根据行为类型提取行为。这是一种非常流行的方法,您可能会在cats
,circe
等库中看到这种方法。
请查看下面的代码示例以获取更多详细信息:
// Type dependent logic interface
trait CreateTopic[T] {
def createTopic(topic: String, source: String): String // put desired result type here
}
object CreateTopic {
implicit def recordCreateTopic[T <: SpecificRecordBase](implicit tag: ClassTag[T]): CreateTopic[T] = {
(topic: String, source: String) => ??? // create topic for record base
}
implicit val stringCreateTopic: CreateTopic[String] = {
(topic: String, source: String) => ??? // create topic for record base
}
}
import CreateTopic._
// implementation will be substituted by compiler based on it's type, from implicit context
def process[T](/*other arguments*/)(implicit create: CreateTopic[T]): Unit = {
create.createTopic(topic, source)
/// other operations
}
不好意思,我不是Kafka专家,所以请纠正我,如果您发现某些部分,从Kafka的角度来看并没有任何意义。
希望这会有所帮助!