[英]Scala Trait type mismatch
I have some Kafka Channel hierarchy that I am using in my project:我在我的项目中使用了一些 Kafka Channel 层次结构:
My base trait is:我的基本特征是:
trait SendChannel[A, B] extends CommunicationChannel {
def send(data:A): B
}
Now I have a common kafka send Channel like现在我有一个常见的 kafka 发送频道,例如
trait CommonKafkaSendChannel[A, B, Return] extends SendChannel[A, Return] {
val channelProps: KafkaSendChannelProperties
val kafkaProducer: Producer[String, B]
override def close(): Unit = kafkaProducer.close()
}
Now there are 2 variants of CommanKafkaSendChannel, one is with callback and one is with Future:现在 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
definition: 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)
}
Now based on the configuration value I select the proper type of channel on run time like below.现在根据配置值,我在运行时选择正确类型的通道,如下所示。 I am creating actor with right type of channel which will send the data to kafka:我正在创建具有正确类型通道的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)
Actor definition:演员定义:
object IngestionRouterActor {
def props[V](config: Config, sendChannel: SendChannel[V, Unit]): Props =
Props(classOf[IngestionActor[V]], config, sendChannel)
}
The problem is when I use KafkaSendChannelWithCallback
my code compiles properly however when I use KafkaSendChannelWithFuture
it gives me below error on actor =
declaration:问题是当我使用KafkaSendChannelWithCallback
我的代码编译正确,但是当我使用KafkaSendChannelWithFuture
它给我以下关于actor =
声明的错误:
[error]IngestionActor.scala:32: pattern type is incompatible with expected type; [错误] IngestionActor.scala:32: 模式类型与预期类型不兼容; [error] found : KafkaSendChannelWithFuture[String,V] [error] required: SendChannel[V,Unit] [错误] 发现:KafkaSendChannelWithFuture[String,V] [error] 需要:SendChannel[V,Unit]
As both the channel definitions are extended from SendChannel
, this code should have compiled without any error.由于两个通道定义都是从SendChannel
扩展而来的,因此此代码应该已编译且没有任何错误。 I am not sure why it is not compiling.我不确定为什么它没有编译。 Thanks谢谢
The Props
for IngestionActor
takes a SendChannel[V, Unit]
.该Props
为IngestionActor
需要SendChannel[V, Unit]
。 Passing in a KafkaSendChannelWithCallback
to this argument works because it's a SendChannel[V, Unit]
.将KafkaSendChannelWithCallback
传递给这个参数是有效的,因为它是一个SendChannel[V, Unit]
。
On the other hand, KafkaSendChannelWithFuture
is a SendChannel[V, Future[RecordMetadata]]
.另一方面, KafkaSendChannelWithFuture
是一个SendChannel[V, Future[RecordMetadata]]
。 A SendChannel[V, Future[RecordMetadata]]
is not a SendChannel[V, Unit]
. SendChannel[V, Future[RecordMetadata]]
不是SendChannel[V, Unit]
。
One option is to redefine the Props
to take a SendChannel[V, Any]
, since Any
is a supertype of both Unit
and Future
:一种选择是重新定义Props
以采用SendChannel[V, Any]
,因为Any
是Unit
和Future
的超类型:
def props[V](config: Config, sendChannel: SendChannel[V, Any]): Props = ???
At this point, the compiler is still unhappy because SendChannel
, being a generic type, is invariant by default.此时,编译器仍然不满意,因为SendChannel
作为泛型类型,默认情况下是不变的。 In other words, neither SendChannel[V, Unit]
nor SendChannel[V, Future[RecordMetadata]]
are of type SendChannel[V, Any]
.换句话说, SendChannel[V, Unit]
和SendChannel[V, Future[RecordMetadata]]
都不是SendChannel[V, Any]
。
To change that, make SendChannel
covariant on the second type parameter (by adding a +
in front of the B
):要更改它,请在第二个类型参数上使SendChannel
协变(通过在B
前面添加一个+
):
trait SendChannel[A, +B] extends CommunicationChannel {
def send(data: A): B
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.