簡體   English   中英

將通用服務與其實現和子類型綁定

[英]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))

在嘗試解決代碼部分中提到的12 時,有沒有辦法解決這種情況?

(我可能會在很大程度上重申您已經知道的內容)

撇開與 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

說,你有一個擴展BaseReportingHotReporting類,因此你有這樣的東西

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM