日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

svn: 没有演进历程信息_使用默认方法的接口演进–第二部分:接口

發(fā)布時(shí)間:2023/12/3 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 svn: 没有演进历程信息_使用默认方法的接口演进–第二部分:接口 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

svn: 沒有演進(jìn)歷程信息

引入了默認(rèn)方法以啟用接口演進(jìn)。 如果向后兼容性是不可替代的,則僅限于向接口添加新方法(這是它們?cè)贘DK中的唯一用法)。 但是,如果希望客戶端更新其代碼,則可以使用默認(rèn)方法逐步演化接口而不會(huì)引起編譯錯(cuò)誤,從而使客戶端有時(shí)間將其代碼更新為新版本的接口。

這個(gè)小型系列的第一部分說明了默認(rèn)實(shí)現(xiàn)如何允許在不破壞客戶端代碼的情況下添加,替換和刪除方法。 我愚蠢地宣布,“以后的文章將探討替換整個(gè)接口的方法”,同時(shí)也不會(huì)破壞客戶端代碼。

好吧,您現(xiàn)在正在閱讀這篇文章,不幸的摘要是:

我無法使其工作。

為什么? 泛型。

到底為什么 你真的想知道嗎 好吧,那么請(qǐng)繼續(xù)閱讀,但是這篇文章的其余部分實(shí)際上只是對(duì)我如何成為障礙的描述,因此不要期望太多。 (大激勵(lì),是嗎?)

總覽

在描述我嘗試過的方法和失敗的方法之前,我先定義要解決的問題。

問題陳述

這就是我們要做的:

假定您的代碼庫包含一個(gè)接口,您的客戶端可以用所有可以想象的方式使用該接口:它們具有自己的實(shí)現(xiàn),使用其實(shí)例調(diào)用您的代碼,并且您的代碼返回此類實(shí)例,當(dāng)然他們將其用作參數(shù)的類型和返回值。

現(xiàn)在,您要實(shí)質(zhì)性地更改接口:以無法用對(duì)單個(gè)方法的更改來表示的方式對(duì)其進(jìn)行重命名,移動(dòng)或修改。 (但是從提供一個(gè)版本到另一個(gè)版本的角度來看,這兩個(gè)接口仍然是等效的。)

您可以執(zhí)行此操作,發(fā)布包含更改的新版本,并告訴您的客戶端修復(fù)其導(dǎo)致的編譯錯(cuò)誤。 如果他們的代碼與您的代碼高度耦合,那么他們可能必須在單獨(dú)的分支中執(zhí)行此操作以花一些時(shí)間在代碼上,但這就是生活,對(duì)嗎? 不過,您真是個(gè)好人,因此,與其要求費(fèi)時(shí)的一天,不如讓他們有機(jī)會(huì)隨著時(shí)間的推移(例如,直到下一個(gè)版本)逐漸更改其代碼,而沒有任何編譯錯(cuò)誤。

(請(qǐng)注意,這是接下來所有內(nèi)容的主要要求。我首先忽略了這是否是個(gè)好主意。我只是想看看自己能走多遠(yuǎn)。)

我認(rèn)為甚至有機(jī)會(huì)實(shí)現(xiàn)這一目標(biāo)的唯一方法是定義一個(gè)過渡階段,在該階段中,新舊版本的接口都將共存。 因此,我們真正需要的是一種通用的逐步方法,該方法如何將實(shí)現(xiàn),調(diào)用者和聲明從一個(gè)接口轉(zhuǎn)移到另一個(gè)接口。

想法

在發(fā)布這篇文章時(shí),我對(duì)它的工作方式有一個(gè)具體的想法。 基本上與我在方法中使用的方法相同。

不斷發(fā)展的接口方法

使用默認(rèn)方法添加,替換或刪除接口的單個(gè)??方法非常簡(jiǎn)單,通常包括三個(gè)步驟(在某些情況下更少):

  • 新版本:庫的新版本發(fā)布,其中界面定義是過渡性的,并結(jié)合了舊的和新的所需輪廓。 默認(rèn)方法可確保所有外部實(shí)現(xiàn)和調(diào)用仍然有效,并且在更新時(shí)不會(huì)出現(xiàn)編譯錯(cuò)誤。
  • 過渡:然后客戶有時(shí)間從舊大綱過渡到新大綱。 同樣,默認(rèn)方法可確保適應(yīng)的外部實(shí)現(xiàn)和調(diào)用有效,并且可以進(jìn)行更改而不會(huì)產(chǎn)生編譯錯(cuò)誤。
  • 新版本:在新版本中,該庫刪除了舊輪廓的殘差。 鑒于客戶端明智地利用了自己的時(shí)間并進(jìn)行了必要的更改,因此發(fā)布新版本不會(huì)導(dǎo)致編譯錯(cuò)誤。

如果您對(duì)這些步驟的詳細(xì)說明感興趣,可以閱讀我的早期文章 。

改進(jìn)界面

對(duì)于這種情況,這種方法似乎也很有意義,所以我坐下來進(jìn)行了探討。

如果整個(gè)接口發(fā)生變化,則要稍微復(fù)雜一點(diǎn),因?yàn)樵诜椒▋H具有調(diào)用者和實(shí)現(xiàn)的地方,該接口也是一種類型,即可以在聲明中使用。 這使得必須區(qū)分三種使用接口的方式:

  • 內(nèi)部使用 ,您在其中擁有實(shí)現(xiàn)和使用接口的代碼
  • 已發(fā)布的使用 ,您擁有實(shí)現(xiàn),但客戶端調(diào)用了代碼
  • 外部使用 ,其中客戶端擁有實(shí)現(xiàn)和使用接口的代碼

起作用的部分采用與演化方法相同的方法:

  • 新版本:使用新界面發(fā)布新版本,以擴(kuò)展舊版本。 讓所有內(nèi)部代碼實(shí)現(xiàn)并使用新接口。 所有已發(fā)布的代碼將使用舊接口聲明參數(shù)類型,并使用新接口返回類型。 如果必須轉(zhuǎn)換實(shí)例,則可以使用適配器來完成。 現(xiàn)在忽略參數(shù)化類型,此更改將不會(huì)導(dǎo)致客戶端代碼中的編譯錯(cuò)誤。
  • 過渡:發(fā)布后,客戶端更改其代碼。 從舊接口的實(shí)現(xiàn)(已更改為實(shí)現(xiàn)新接口的實(shí)現(xiàn))和您已發(fā)布的代碼返回的實(shí)例開始,它們可以開始聲明新類型的實(shí)例,更新將它們傳遞給它們的方法的參數(shù)類型,等等。上。 如有必要,可以暫時(shí)使用適配器通過新接口與舊實(shí)例進(jìn)行交互。
  • 新版本:發(fā)布一個(gè)刪除舊界面的版本。

與不斷發(fā)展的方法相同,新接口中的默認(rèn)實(shí)現(xiàn)允許客戶端代碼停止明確實(shí)現(xiàn)舊接口,從而可以在第二個(gè)版本中將其刪除。 此外,舊接口上的便捷asNew()方法可以調(diào)用適配器以使其自身適應(yīng)新接口。

我掩飾了一些細(xì)節(jié),但我希望你相信我,這是可行的。 現(xiàn)在讓我們回到泛型…

障礙

提出的方法中的關(guān)鍵部分是已發(fā)布的代碼。 它由您的客??戶調(diào)用,因此第一個(gè)發(fā)行版必須以兼容的方式對(duì)其進(jìn)行更改。 并且由于所有內(nèi)部代碼都需要新接口,因此它必須從Old到New 。

沒有泛型,它可能看起來像這樣:

在已發(fā)布的代碼中將“舊”轉(zhuǎn)換為“新”

// in version 0 public Old doSomething(Old o) {// 'callToInternalCode' requires an 'Old'callToInternalCode(o);return o; }// in version 1 the method still accepts 'Old' but returns 'New' public New doSomething(Old o) {// 'callToInternalCode' now requires a 'New'New n = o.asNew();callToInternalCode(n);return n; }

好的,到目前為止很好。 現(xiàn)在,讓我們看看泛型的外觀。

在已發(fā)布的代碼中將“舊”轉(zhuǎn)換為“新” –泛型

// in version 0 public Container<Old> doSomething(Container<Old> o) {// 'callToInternalCode' requires a 'Container<Old>'callToInternalCode(o);return o; }// in version 1 // doesn't work because it breaks assignments of the return value public Container<New> doSomething(Container<Old> o) {// 'callToInternalCode' requires a 'Container<New>'// but we can not hand an adapted version to 'callToInternalCode'// instead we must create a new containerNew nInstance = o.get().asNew();Container<New> n = Container.of(nInstance);callToInternalCode(n);return n; }

因此,使用已發(fā)布的代碼層從舊界面適應(yīng)新界面通常不起作用,原因至少有兩個(gè):

  • 由于Java中泛型的不變性,返回值的所有分配都將中斷:

    不變性打破分配 Container<Old> old = // ... // works in version 0; breaks in version 1 Container<Old> o = published.doSomething(old);
  • 不能將同一Container實(shí)例從已發(fā)布傳遞到內(nèi)部代碼。 這導(dǎo)致兩個(gè)問題:
    • 創(chuàng)建一個(gè)新容器可能很困難或不可能。

該死的…

發(fā)布時(shí)間由交通運(yùn)輸?shù)娜A盛頓州部門在CC-BY-NC-ND 2.0 。

從一開始,我就感到仿制藥會(huì)很麻煩-回想起來,這實(shí)際上很明顯。 當(dāng)涉及類型時(shí),泛型怎么可能不是問題。 因此,也許我應(yīng)該先嘗試解決難題。

可能繞行

在將我的頭撞在墻上一段時(shí)間之后,我仍然沒有找到解決這個(gè)問題的通用方法。 但是我想出了一些可能有助于解決特殊情況的想法。

通配符

您可以檢查已發(fā)布的內(nèi)部代碼是否充分利用了通配符(請(qǐng)記住PECS )。 您也可以建議客戶如何使用它們。

根據(jù)情況,這可能會(huì)產(chǎn)生解決方案。

專用接口,類,實(shí)例

根據(jù)具體的代碼,可以提供使用舊接口的已發(fā)布接口,類或?qū)嵗男掳姹尽?如果可以通過讓客戶端選擇使用依賴于舊接口的接口,類或?qū)嵗€是依賴于新接口的接口,類或?qū)嵗姆绞絹硖幚泶a,則各個(gè)實(shí)現(xiàn)不必進(jìn)行轉(zhuǎn)換。

但這可能會(huì)將舊界面推回內(nèi)部代碼,而內(nèi)部代碼剛剛更新為僅使用新接口。 聽起來也不好。

容器適配器

您可以在已發(fā)布的代碼中為與舊接口一起使用的容器提供適配器。 這實(shí)際上將允許您在這些容器上調(diào)用asNew() 。

(出于一個(gè)不相關(guān)的原因,我目前正在為某些JDK集合進(jìn)行此類轉(zhuǎn)換。下一版本的LibFX將包含它們;如果您好奇,可以在GitHub上查看演示。)

算了!

這一切又是為了什么? 為了防止客戶創(chuàng)建分支,在將所有內(nèi)容合并回master之前花一些時(shí)間在那里修復(fù)問題嗎? 算了!

在這一點(diǎn)上,這是我對(duì)此事的看法。 只要您只處理單個(gè)方法,接口的演變就很順利,但是當(dāng)您要替換整個(gè)接口時(shí),這似乎會(huì)很痛苦。 因此,除非有充分的理由介紹所有這些復(fù)雜性,否則我將以困難的方式進(jìn)行操作,然后讓客戶對(duì)其進(jìn)行分類。 還是根本不做。

而且,如果您只是重命名或移動(dòng)界面,無論如何,大部分甚至全部工作都可以通過簡(jiǎn)單的搜索替換來完成。

反射

我們重申了如何將默認(rèn)方法用于發(fā)布,過渡和發(fā)布三部分的界面演化。 盡管這對(duì)單個(gè)方法有效,但我們發(fā)現(xiàn)它無法替換整個(gè)接口。 主要問題是參數(shù)類型的不變性使我們無法使用已發(fā)布的代碼作為適應(yīng)層。

即使我們看到了一些解決該問題的方法,也沒有一個(gè)好的解決方案脫穎而出。 最后,看起來不值得麻煩。

我有事嗎 還是整個(gè)想法愚蠢? 為什么不發(fā)表評(píng)論!

翻譯自: https://www.javacodegeeks.com/2015/04/interface-evolution-with-default-methods-part-ii-interfaces.html

svn: 沒有演進(jìn)歷程信息

總結(jié)

以上是生活随笔為你收集整理的svn: 没有演进历程信息_使用默认方法的接口演进–第二部分:接口的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。