Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/extjs/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java泛型(1/N)类型_Java_Generics_Types - Fatal编程技术网

Java泛型(1/N)类型

Java泛型(1/N)类型,java,generics,types,Java,Generics,Types,我想声明泛型类型是类型的子集之一,但我不确定如何声明。以下是我的情况的简化版本: 模块与事件通信。有不同类型的事件。模块可以使用不同的方法使用不同的事件类型 class EventProducerA implements Producer<EventTypeA>{ @Override public EventTypeA produce_event(){ return new EventTypeA(...); } } class EventPr

我想声明泛型类型是类型的子集之一,但我不确定如何声明。以下是我的情况的简化版本:

模块与事件通信。有不同类型的事件。模块可以使用不同的方法使用不同的事件类型

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){
        ...
    }
}
类EventProducerA实现Producer{
@凌驾
公共事件类型A生成_事件(){
返回新的EventTypeA(…);
}
}
类EventProducerB实现Producer{
@凌驾
公共事件类型B生成_事件(){
返回新的EventTypeB(…);
}
}
类事件消费者{
公共无效馈送事件(EventTypeA ev){
...
}
公共无效源事件(EventTypeB ev){
...
}
}
现在,我有了一个主类,我在其中链接这些模块。我想要代码:

Producer<EventTypeA OR EventType B> producer = some_flag?new EventProducerA():new EventProducerB();
Consumer consumer = new EventConsumer()
consumer.feed_event(producer.produce_event());
Producer-Producer=some_标志?new EventProducerA():new EventProducerB();
消费者消费者=新事件消费者()
consumer.feed_事件(producer.product_事件());
如果生产者生成了消费者未处理的某些EventTypeC,则会导致编译错误

但不幸的是,Java中没有泛型类型的OR选项


那最好的办法是什么呢?我是否被迫使用丑陋的强制转换解决方案?

即使尝试过,也不会有令人讨厌的强制转换解决方案起作用,因为如果
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());
}
if(某些_标志){
Producer-producera=新事件producera();
消费者=新事件消费者();
consumer.feed_事件(producer.product_事件());
}否则{
Producer-producerb=新事件producerb();
消费者=新事件消费者();
consumer.feed_事件(producer.product_事件());
}

不要想入非非。

即使您尝试过,也不会有糟糕的强制转换解决方案奏效,因为如果
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());
}
if(某些_标志){
Producer-producera=新事件producera();
消费者=新事件消费者();
consumer.feed_事件(producer.product_事件());
}否则{
Producer-producerb=新事件producerb();
消费者=新事件消费者();
consumer.feed_事件(producer.product_事件());
}

不要装腔作势。

不幸的是,你所要求的无法实现。如果您仔细考虑一下,就会删除关于
product\u event
生成的类型的静态信息,从而防止编译器知道应该使用什么样的
feed\u 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){
        ...
    }
}
接口IProducer
{
无效消费事件(消费者);
}
抽象类生产者:IProducer
{
}
类EventProducerA实现Producer{
@凌驾
公共事件类型A生成_事件(){
返回新的EventTypeA(…);
}
@覆盖无效消费(消费者)
{
consumer.feed_事件(product_event());
}
}
类事件消费者{
公共无效源事件(IProducer p)
{
p、 消耗(这个);
}
公共无效馈送事件(EventTypeA ev){
...
}
公共无效源事件(EventTypeB ev){
...
}
}

最后,您可能想看看如何使用函数式编程语言中的代数数据类型

不幸的是,你的要求无法实现。如果您仔细考虑一下,就会删除关于
product\u event
生成的类型的静态信息,从而防止编译器知道应该使用什么样的
feed\u 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){
        ...
    }
}
接口IProducer
{
无效消费事件(消费者);
}
抽象类生产者:IProducer
{
}
类EventProducerA实现Producer{
@凌驾
公共事件类型A生成_事件(){
返回新的EventTypeA(…);
}
@覆盖无效消费(消费者)
{
consumer.feed_事件(product_event());
}
}
类事件消费者{
公共无效源事件(IProducer p)
{
p、 消耗(这个);
}
公共无效馈送事件(EventTypeA ev){
...
}
公共无效源事件(EventTypeB ev){
...
}
}
最后,您可能想看看如何使用函数式编程语言中的代数数据类型

总有办法

首先为两个事件创建公共接口

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);
Producer总有办法

首先为两个事件创建公共接口

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

ProducerAh。这很好,除了可能的消费者群体不断扩大,而且事件类型相对较少之外。但是,我可以将accept方法放在所有事件的基类中,并让“`@覆盖public void accept(Consumer Consumer){Consumer.feed_event(this);}```。只是我现在需要某种方法来获取继承该方法的类的类型,我认为Java中也没有实现该方法@Peter仍然认为这不是一个问题,您可以传递consumer的基类,或者您甚至可以为此创建单独的接口(如果您使用的是Java8,那么您可以提供默认实现),这可能很麻烦,但您需要记住的是添加新的int