![](/img/trans.png)
[英]Generic iterator for an interface and its subclasses and its types and subtypes
[英]Binding generic service with its implementation and subtypes
免责声明:请耐心等待我提供大量代码来解释该场景。
在其中一个 maven 模块(核心)中,我们有以下类:
abstract class ReportingEvent {
}
abstract class Element {
public <E extends ReportingEvent> Optional<E> getReportEvent() {
return Optional.empty();
}
}
服务,例如:
public interface Reporting<E extends ReportingEvent> {
void report(E event);
}
interface InternalService {
}
public class InternalServiceImpl implements InternalService {
@Inject
Reporting<ReportingEvent> reporting; // 1. Possible to use a generic type? How?
private void reportEvents(BatchRequest batchRequest) {
batchRequest.stream()
// section below is of importance
.map(m -> m.getEntity().getReportEvent()) // the generic method from 'Element'
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(event -> reporting.report(event)); // method from 'Reporting'
}
}
class CoreBindingModule extends AbstractModule {
protected void configure() {
bind(InternalService.class).to(InternalServiceImpl.class).in(Singleton.class);
}
}
此外,在我们部署的另一个 maven 模块(消费者)中,我们有与上述相关并实现上述内容的类:
abstract class BaseReporting extends ReportingEvent {
}
class ColdReporting extends BaseReporting {
}
abstract class Node extends Element {
}
class Cold extends Node {
@Override
public Optional<ColdReporting> getReportEvent() {
return Optional.ofNullable(new ColdReporting()); // some business logic
}
}
class ReportingImpl implements Reporting<ReportingEvent> { // 2. Use 'BaseReporting' here
void report(ReportingEvent event){}
}
class ConsumerBindingModule extends AbstractModule {
protected void configure() {
bind(new TypeLiteral<Reporting<ReportingEvent>>() {}).to(ReportingImpl.class).in(Singleton.class);
}
}
上面的代码工作正常。 但问题是使用了与模块不太相关的类型。
A...所以如果我将消费者模块中的绑定更改为
bind(new TypeLiteral<Reporting<BaseReporting>>() {}).to(ReportingImpl.class).in(Singleton.class);
和
class ReportingImpl implements Reporting<BaseReporting> {
void report(BaseReporting event){}
}
我收到一个错误
No implementation for Reporting<ReportEvent> was bound. while locating Reporting<ReportEvent> for field at InternalServiceImpl.reporting(InternalServiceImpl.java:21)
这是相关的,无论如何我都无法在核心模块中使用Reporting<BaseReporting>
。
B...另一方面,如果我尝试将Reporting
注入为:
@Inject
Reporting<? extends ReportingEvent> reporting;
然后 IDEA 声明
Required type: capture of ? Provided: ReportingEvent
在线上
...forEach(event -> reporting.report(event))
在尝试解决代码部分中提到的1和2 时,有没有办法解决这种情况?
(我可能会在很大程度上重申您已经知道的内容)
撇开与 Guice 相关的模块和配置,您的问题可以写成
Reporting<ReportingEvent> reportingEvent = new ReportingImpl();
Reporting<? extends ReportingEvent> reporting = baseReporting;
reporting.report(reportingEvent); //won't work
这与
List<? extends String> list = new ArrayList<>();
list.add("a"); //won't work
说,你有一个扩展BaseReporting
的HotReporting
类,因此你有这样的东西
public class ReportingImpl implements Reporting<ReportingEvent> {
public void report(ReportingEvent event){}
}
public class ColdReportingImpl implements Reporting<ColdReporting> {
public void report(ColdReporting event){}
}
public class HotReportingImpl implements Reporting<HotReporting> {
public void report(HotReporting event){}
}
假设您HotReportingImpl
为字段Reporting<? extends ReportingEvent> reporting
注入了一个HotReportingImpl
Reporting<? extends ReportingEvent> reporting
Reporting<? extends ReportingEvent> reporting
。
在您的代码中,如果m.getEntity().getReportEvent()
返回ColdReporting
怎样? 它与这里的report
方法所期望的不兼容(一个HotReporting
)。
选项1:
我会尝试摆脱泛型类型参数并将Reporting
定义为
public interface Reporting {
void report(ReportingEvent event);
}
public class BaseReportingImpl implements Reporting {
@Override
public void report(ReportingEvent event) {
}
}
//... and so on
问题:
ReportingEvent
的确切子类型(需要不好的类型转换)。HotReportingImpl
可以获取ColdReporting
对象作为参数。选项 2:
您可以通过向其添加类型参数来使InternalService
泛型。
如果实现类Reporting
必须处理的具体类型ReportingEvent
,那么它看起来不正确的Element
返回基本类型( ReportingEvent
)。
看看Joshua Bloch 的 Typesafe 异构容器。 你的问题与此重叠。 您可以使用该类型参数维护从ReportingEvent
的类型到相应的Reporting
子类的映射。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.