Java Generic(N中的1个)类型

时间:2016-02-02 21:52:44

标签: java generics types

我想声明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选项。

那么最好的做法是什么?我被迫使用难看的铸造解决方案吗?

3 个答案:

答案 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);