![](/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.