我想声明Generic Type是类型的子集之一,但我不确定如何。以下是我的情况的简化版本:
模块与事件通信。有不同类型的事件。模块可以使用不同的方法使用不同的事件类型。
class EventProducerA implements Producer<EventTypeA>{
@Override
public EventTypeA produce_event(){
return new EventTypeA(...);
}
}
class EventProducerB implements Producer<EventTypeB>{
@Override
public EventTypeB produce_event(){
return new EventTypeB(...);
}
}
class EventConsumer{
public void feed_event(EventTypeA ev){
...
}
public void feed_event(EventTypeB ev){
...
}
}
现在,我有一个主类,我链接这些模块。我想要代码:
Producer<EventTypeA OR EventType B> producer = some_flag?new EventProducerA():new EventProducerB();
Consumer consumer = new EventConsumer()
consumer.feed_event(producer.produce_event());
如果生产者生成了消费者未处理的某些EventTypeC,则会导致编译错误。
但遗憾的是,Java中的通用类型没有OR选项。
那么最好的做法是什么?我被迫使用难看的铸造解决方案吗?
答案 0 :(得分:4)
即使您尝试使用它们,即使是讨厌的强制转换解决方案也不会起作用,因为如果EventConsumer
对不同的事件类型有不同的重载,那么您必须在编译时知道在哪个代码路径中选择了哪个重载。做尴尬但直截了当的事情:
if (some_flag) {
Producer<EventTypeA> producer = new EventProducerA();
Consumer consumer = new EventConsumer();
consumer.feed_event(producer.produce_event());
} else {
Producer<EventTypeB> producer = new EventProducerB();
Consumer consumer = new EventConsumer();
consumer.feed_event(producer.produce_event());
}
不要试图变幻想。
答案 1 :(得分:1)
不幸的是,你提出的要求无法完成。如果您考虑一下,您将删除有关produce_event
生成的类型的静态信息,从而阻止编译器知道它应该使用的feed_event
的重载。
作为替代解决方案,您可以保持简单,添加一些样板代码:
if(some_flag)
{
EventProducerA producer = new EventProducerA();
Consumer consumer = new EventConsumer();
consumer.feed_event(producer.produce_event());
}
else
{
EventProducerA producer = new EventProducerA();
Consumer consumer = new EventConsumer();
consumer.feed_event(producer.produce_event());
}
如果你不喜欢这个解决方案,你需要找到一种双重调度方式。
interface IProducer
{
void consume_event(Consumer consumer);
}
abstract class Producer<T> : IProducer
{
}
class EventProducerA implements Producer<EventTypeA>{
@Override
public EventTypeA produce_event(){
return new EventTypeA(...);
}
@Override void consume(Consumer consumer)
{
consumer.feed_event(produce_event());
}
}
class EventConsumer{
public void feed_event(IProducer p)
{
p.consume(this);
}
public void feed_event(EventTypeA ev){
...
}
public void feed_event(EventTypeB ev){
...
}
}
最后,您可能希望看一下尝试使用函数式编程语言中可以找到的Either
代数数据类型的等价物。 This Q&A shows how you could simulate it in Java
答案 2 :(得分:1)
总有办法,
首先为您的活动创建通用界面
interface EventType {
void accept(EventConsumer consumer);
}
现在实施
class EventTypeA implements EventType {
@Override
public void accept(EventConsumer consumer) {
consumer.feed_event(this);
}
}
以及如何使用它?简单
Producer<? extends EventType> producer = condition ? new EventProducerA() : new EventProducerB();
EventConsumer consumer = new EventConsumer();
EventType eventType= producer.produce_event();
eventType.accept(consumer);