繁体   English   中英

Scala Trait类型不匹配

[英]Scala Trait type mismatch

我在我的项目中使用了一些 Kafka Channel 层次结构:

我的基本特征是:

trait SendChannel[A, B] extends CommunicationChannel {
  def send(data:A): B
}

现在我有一个常见的 kafka 发送频道,例如

trait CommonKafkaSendChannel[A, B, Return] extends SendChannel[A, Return] {
val channelProps: KafkaSendChannelProperties
val kafkaProducer: Producer[String, B]
 override def close(): Unit = kafkaProducer.close()
}

现在 CommanKafkaSendChannel 有两种变体,一种带有回调,一种带有 Future:

trait KafkaSendChannelWithFuture[A, B] extends CommonKafkaSendChannel[A, B, Future[RecordMetadata]] {
override def send(data: A): Future[RecordMetadata] = Future {
  kafkaProducer.send(new ProducerRecord[String, B](channelProps.topic)).get
}
}

KafkaSendChannelWithCallback定义:

object KafkaSendChannelWithCallback {

def apply[A, B](oChannelProps: KafkaSendChannelProperties,
              oKafkaProducer: Producer[String, B],
              oCallback: Callback): KafkaSendChannelWithCallback[A, B] =
new KafkaSendChannelWithCallback[A,B] {
  override val channelProps: KafkaSendChannelProperties = oChannelProps
  override val kafkaProducer: Producer[String, B] = oKafkaProducer
  override val callback: Callback = oCallback
}
}

trait KafkaSendChannelWithCallback[A, B] extends CommonKafkaSendChannel[A, B, Unit] {

  val callback: Callback

override def send(data: A): Unit =
kafkaProducer.send(new ProducerRecord[String, B](channelProps.topic), callback)
}

现在根据配置值,我在运行时选择正确类型的通道,如下所示。 我正在创建具有正确类型通道的actor,它将数据发送到kafka:

  val sendChannel = kafkaChannel.channel(config, actorSystem).fold(
    error => {
      logger.error("Exception while instantiating the KafkaSendChannel")
      throw error
    },
    success => success
  )

actor = actorSystem.actorOf(IngestionActor.props(config, sendChannel), name = ACTOR_NAME)

演员定义:

object IngestionRouterActor {
  def props[V](config: Config, sendChannel: SendChannel[V, Unit]): Props =
Props(classOf[IngestionActor[V]], config, sendChannel)
}

问题是当我使用KafkaSendChannelWithCallback我的代码编译正确,但是当我使用KafkaSendChannelWithFuture它给我以下关于actor =声明的错误:

[错误] IngestionActor.scala:32: 模式类型与预期类型不兼容; [错误] 发现:KafkaSendChannelWithFuture[String,V] [error] 需要:SendChannel[V,Unit]

由于两个通道定义都是从SendChannel扩展而来的,因此此代码应该已编译且没有任何错误。 我不确定为什么它没有编译。 谢谢

PropsIngestionActor需要SendChannel[V, Unit] KafkaSendChannelWithCallback传递给这个参数是有效的,因为它是一个SendChannel[V, Unit]

另一方面, KafkaSendChannelWithFuture是一个SendChannel[V, Future[RecordMetadata]] SendChannel[V, Future[RecordMetadata]]不是SendChannel[V, Unit]

一种选择是重新定义Props以采用SendChannel[V, Any] ,因为AnyUnitFuture的超类型:

def props[V](config: Config, sendChannel: SendChannel[V, Any]): Props = ???

此时,编译器仍然不满意,因为SendChannel作为泛型类型,默认情况下是不变的。 换句话说, SendChannel[V, Unit]SendChannel[V, Future[RecordMetadata]]都不是SendChannel[V, Any]

要更改它,请在第二个类型参数上使SendChannel协变(通过在B前面添加一个+ ):

trait SendChannel[A, +B] extends CommunicationChannel {
  def send(data: A): B
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM