亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何處理一個每一步都可以是終端操作的流暢界面?

如何處理一個每一步都可以是終端操作的流暢界面?

ITMISS 2022-11-10 16:39:41
我正在構建一個大致像這樣工作的流暢 API(假設存在一個返回 a 的Person帶有 getter的類):getIdLongString result = context.map(Person::getId)     .pipe(Object::toString)     .pipe(String::toUpperCase)     .end(Function.identity())如您所見,只有.end-function 充當終端運算符。這使上述 API 的整體使用.end(Function.identity())變得混亂,因為即使前面的.pipe-call 已經具有正確的類型,我也經常不得不以 -call 結束。有什么方法可以制作一個 fluent-API,使其一部分既是終端操作員又是“橋接操作員”?我只是不想用專門的 pipe變體pipeTo(例如,只接受 aFunction<CurrentType, ExpectedType>和內部調用的管道.end)來模擬所述行為,因為它迫使用戶考慮 API 的一個非常特定的部分,這對我來說似乎是不必要的。編輯:根據要求簡化上下文實現:class Context<InType, CurrentType, TargetType> {    private final Function<InType, CurrentType> getter;    public Context(Function<InType, CurrentType> getter) {        this.getter = getter;    }    public <IntermediateType> Context<InType, IntermediateType, TargetType>    pipe(Function<CurrentType, IntermediateType> mapper) {        return new Context<>(getter.andThen(mapper));    }    public Function<InType, TargetType> end(Function<CurrentType, TargetType> mapper) {        return getter.andThen(mapper);    }}//usageFunction<Person, String> mapper = new Context<Person, Long, String>(Person::getId)    .pipe(Object::toString)    .pipe(String::toUpperCase)    .end(Function.identity());mapper.apply(new Person(...))
查看完整描述

3 回答

?
慕斯709654

TA貢獻1840條經驗 獲得超5個贊

如果我了解您要查找的內容,我會重載end()并擺脫最后一個函數組合:


public Function<InType, CurrentType> end() {

    return this.getter;

}

進一步思考,我認為Context可以消除類的第三個類型參數,因為僅在方法級別需要中間類型。檢查這個:


class OtherContext<I, O> {


    private final Function<I, O> getter;


    public OtherContext(Function<I, O> getter) {

        this.getter = getter;

    }


    public <T> OtherContext<I, T> pipe(Function<O, T> mapper) {


        return new OtherContext<I, T>(getter.andThen(mapper));

    }


    public <T> Function<I, T> end(Function<O, T> mapper) {

        return getter.andThen(mapper);

    }


    public Function<I, O> end() {

        return getter;

    }

}


查看完整回答
反對 回復 2022-11-10
?
慕尼黑的夜晚無繁華

TA貢獻1864條經驗 獲得超6個贊

您不能在 Java 中定義具有相同名稱和不同返回類型的方法。您的方法可能會返回類似的東西Wrapped<T>,而您想要返回T。一般來說,我可能會建議為*andEnd(...)您的每種方法設置類似的東西。管道也是如此pipeAndEnd(...),然后以終端操作結束。這可能會變得乏味,因此如果您有很多方法,您可能想研究一些代碼生成。

另一方面,您似乎正在實現自己的 Stream API 版本。除非您這樣做是出于教育目的,否則使用現有且經過良好測試/記錄的代碼(尤其是標準 jdk 的代碼部分)幾乎總是比重新實現您自己的相同版本更好。


查看完整回答
反對 回復 2022-11-10
?
陪伴而非守候

TA貢獻1757條經驗 獲得超8個贊

我遇到的主要問題是任何pipe步驟都可能是終端操作。正如每個答案和主要帖子下面的討論中所述:在java中不可能使用兩次具有相同名稱的函數并且一個是終端操作。


我猛烈抨擊這個問題并嘗試了多種方法,但每種方法都不起作用。那是當我意識到我在做的事情本質上與 Javas Stream-API 相同:你有一個起源(源),做一些花哨的東西(管道)然后結束(收集)。如果我們對我的問題應用相同的方案,則不需要進行pipe終端操作,我們只需要另一個操作(例如end)作為終點。由于我對何時可能結束(當前類型必須與另一種類型匹配)有一些擴展要求,因此我end只允許一個上下文特定的函數來實現,該函數只有一個可用的合理實現(很難解釋)。這是當前實現的示例(pipe已重命名為和map):endto


Mapper<Person, PersonDTO> mapper = Datus.forTypes(Person.class, PersonDTO.class).immutable(PersonDTO::new)

    .from(Person::getFirstName).to(ConstructorParameter::bind)

    .from(Person::getLastName)

        .given(Objects::nonNull, ln -> ln.toUpperCase()).orElse("fallback")

        .to(ConstructorParameter::bind)

    .build();

如您所見.to,充當終端操作員,ConstructorParameter::bind如果當前類型與預期類型不匹配,則會抱怨類型不匹配。


參見這里的to部分,這里的實現ConstructorParameter以及它是如何定義的。


查看完整回答
反對 回復 2022-11-10
  • 3 回答
  • 0 關注
  • 131 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號