通用BiFunction接受通用通配符 [英] Generic BiFunction that accepts generic wildcard

查看:92
本文介绍了通用BiFunction接受通用通配符的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个枚举,并希望有一个通用函数可以接受任何实现maker接口的类。

I have an enum and want to have a generic function that could accept any class that implements a maker interface.

public interface IComponentDataExporter { // Marker Interface }

public class ComponentsDataExporter implements IComponentDataExporter { 
  public ComponentTeaser populateFeatured(ComponentTeaserConfiguration componentConfig) { return null; } 
}
public class BusinessComponentsDataExporter implements IComponentDataExporter { // methods } 

public enum ComponentTypeEnum { 
  FEATURED(ComponentsDataExporter::populateFeatured); 
  
  public final BiFunction<? super IComponentDataExporter, ComponentTeaserConfiguration, ComponentTeaser> exporter;

  private ComponentTypeEnum( BiFunction<? super IComponentDataExporter, ComponentTeaserConfiguration, ComponentTeaser> exporter) {
  this.exporter = exporter;
  }
}

我遇到此编译错误类型ComponentsDataExporter没有定义适用于此处的populateFeatured(IComponentDataExporter,ComponentTeaserConfiguration)

我的主要问题是 BIFunction 我希望它接受 ComponentsDataExporter BusinessComponentsDataExporter ,这就是为什么我尝试使用通用通配符(?扩展 IComponentDataExporter 和?超级 IComponentDataExporter )。如果我将通配符替换为特定的类,效果很好。

My main issue is BIFunction I want it to accepts either ComponentsDataExporter or BusinessComponentsDataExporter that's why I tried to use a generic wildcard (? extends IComponentDataExporter and ? super IComponentDataExporter). It is working fine if I replace wildcard with a specific class.

抱歉,我的问题不清楚,因此我将尝试解释越来越少的历史。

Sorry for not being clear in my questation so I will try to explain more and little of history.

我想强迫任何添加新枚举值的人提供一种导出数据的方法对于该组件。导出方法的逻辑不能放在Enum中,因为它需要访问spring托管的bean,并且可能有很多业务逻辑。

I want to force whoever adding a new enum value to provide a method which is exporting data for that component. Logic of export method cannot be placed in Enum as it requires access to spring managed beans and may have a lot of business logic.

我已经做到了,并且它可以很好地工作, 演示

I already did that and it was working perefectly, you can have a look on this demo.

我的问题开始于我注意到将所有导出方法放在一个类中会太多,因此我决定采用不同的实现方式( BusinessComponentsDataExporter ComponentsDataExporter )它们每个都处理一组组件。

My problem started when I noticed that having all of export methods in one class will be too much so I decided to have different kind of implementation (BusinessComponentsDataExporter and ComponentsDataExporter) each one of them handles set of components.

为实现这种分离,我添加了一个标记接口,以便可以标记任何导出器类并在Enum中更新BiFunction以使用通配符。因此它可以接受实现我的标记器接口的任何类型的对象。

To do that separation I have added a marker interface so I can mark any exporter class and updated BiFunction in Enum to have wildcard so it can accept any kind of object that implements my marker interface.

BiFunction<? super IComponentDataExporter, ComponentTeaserConfiguration, ComponentTeaser> exporter

我目前正在研究的解决方案正在恢复到旧版的BiFunction,就像演示程序

The solutions I am working on right now is reverting to my old version of BiFunction which was like the demo

BiFunction<ComponentsDataExporter, ComponentTeaserConfiguration, ComponentTeaser>

考虑 ComponentsDataExporter 作为外观,其中包含不同类型的导出程序整个导出逻辑所在的位置( businessExporter contentExporter 等),因此facade将具有所有可以调用的高级方法来自枚举。这是我正在考虑的解决方案的示例

Considering ComponentsDataExporter as facade which have instances of different kind of exporters where the whole exporting logic resides (businessExporter, contentExporter etc) so facade will have all high levels methods that can be called from Enum. Here's example for the solution I am considering right now

推荐答案

仔细阅读错误消息的内容……

Read carefully what your error message says…


„ ... ComponentsDataExporter没有定义populateFeatured(IComponentDataExporter,ComponentTeaserConfiguration) ...

„...ComponentsDataExporter does not define populateFeatured(IComponentDataExporter, ComponentTeaserConfiguration)..."

BiFunction< T,U,R> 被定义为接受两个输入参数 。但是您仅使用 一个 参数定义 populateFeatured(ComponentTeaserConfiguration) ...

BiFunction<T,U,R> is defined to take two input arguments. But you define populateFeatured(ComponentTeaserConfiguration) with only one parameter…

...
public ComponentTeaser populateFeatured(ComponentTeaserConfiguration componentConfig)...
...

所以您 需要 可以将其重写 就像我在这里所做的

So you need to could rewrite it like I do here

...
public static ComponentTeaser populateFeatured( IComponentDataExporter self, ComponentTeaserConfiguration componentConfig )... 
...

注意它是 静态 在我的演示中 。如果要使用方法引用( FEATURED(ComponentsDataExporter :: populateFeatured) ),则方法必须为 static ,或者如果不是 static new ComponentsDataExporter():: populateFeatured )。

Notice it's static in my demo. If you want to use a method reference (FEATURED(ComponentsDataExporter::populateFeatured)) then the method either has to be static or you need an object instance to call it if it's not static (new ComponentsDataExporter()::populateFeatured).

然后是 BiFunction 更改为…

And then the BiFunction changes to…

...
BiFunction< IComponentDataExporter, ComponentTeaserConfiguration, ComponentTeaser >...
...

上限通配符( ?将IComponentDataExporter )扩展为 BiFunction 的第一个类型参数不编译。下限通配符( ?super IComponentDataExporter )实际上可以在那里工作。但这会造成混乱。最好只将其指定为普通的接口类型参数( IComponentDataExporter )。

An upper bound wildcard (? extends IComponentDataExporter) as the first type argument to your BiFunction wouldn't compile. A lower bound wildcard (? super IComponentDataExporter) would actually work there. But it would be confusing. It's better off being specified as simply a normal interface type argument (IComponentDataExporter).

然后将其用作…

ComponentTeaserConfiguration conf = null;
    
BusinessComponentsDataExporter exp = null;
    
ComponentTypeEnum featured = ComponentTypeEnum.FEATURED;
    
ComponentTeaser teaser = featured.export( exp, conf );
    
teaser.tease( );

点击演示顶部的绿色开始按钮,查看其运行情况。

Click the green Start button at the top of the demo to see it run.

编辑 :如果我正确理解了您的后续评论,则认为您不想要 BiFunction

根据您的评论收集的内容-和您最初的 populateFeatured(...) 实现-如果您实际上 想要的是 功能 ...

From what I gather from your comments — and your original implementation of populateFeatured(...) — if seems like what you actually want is a Function

...
Function< ComponentTeaserConfiguration, ComponentTeaser >...
...

由于您的问题和评论不清楚,这些建议是基于我假设您的意图的。

Because your questions and comments are not crystal clear, these suggestions are based on what I assume your intention is.


…呼叫将是这样的 ComponentTypeEnum.Featured.exporter.apply(exporterInstance,configObj) ...

…the call will be something like this ComponentTypeEnum.Featured.exporter.apply(exporterInstance, configObj)"

一个您尚未明确说明的事情就是为什么需要将 IComponentDataExporter 传递到 的原因populateFeatured(...) ,因为 ComponentsDataExporter 它自己 IComponentDataExporter 的具体实现。请使用某物更新您的问题,以澄清该问题?

One of the things that you have not made crystal clear is the reason why you need to pass a IComponentDataExporter into populateFeatured(...), given that ComponentsDataExporter is itself a concrete implementation of IComponentDataExporter. Please update your question with something that clarifies that?

这篇关于通用BiFunction接受通用通配符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆