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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

用Java中的抽象类扩展抽象类

發(fā)布時(shí)間:2023/12/3 java 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 用Java中的抽象类扩展抽象类 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

示例問題

當(dāng)我創(chuàng)建Java :: Geci抽象類AbstractFieldsGenerator和AbstractFilteredFieldsGenerator我遇到了一個(gè)不太復(fù)雜的設(shè)計(jì)問題。 我想強(qiáng)調(diào)一下,對于某些人來說,這個(gè)問題和設(shè)計(jì)可能看起來很明顯,但是在我最近與一位初級開發(fā)人員(我的兒子Mihály的交談)中,我的文章比我的英語要好得多,意識到這個(gè)話題可能仍然有價(jià)值。

無論如何。 我有這兩個(gè)類,字段和過濾字段生成器。 第二堂課擴(kuò)展了第一堂課

abstract class AbstractFilteredFieldsGenerator extends AbstractFieldsGenerator {...

添加額外的功能,同時(shí)應(yīng)為具體實(shí)現(xiàn)提供相同的簽名。 這是什么意思?

這些生成器有助于使用反射為特定類生成代碼。 因此,他們處理的輸入信息是Class對象。 字段生成器類具有一個(gè)抽象方法process() ,該方法將為每個(gè)字段調(diào)用。 它是從一個(gè)實(shí)現(xiàn)的方法調(diào)用的,該方法遍歷字段并分別對每個(gè)字段進(jìn)行調(diào)用。 當(dāng)具體類extends AbstractFieldsGenerator并由此實(shí)現(xiàn)此抽象方法時(shí),它將被調(diào)用。 當(dāng)更改相同的具體類以使其extends AbstractFilteredFieldsGenerator ,將僅對過濾后的方法調(diào)用具體方法。 我想要一個(gè)設(shè)計(jì),以便在具體課程中唯一需要的更改是更改名稱。

問題定義 類

以更抽象的方式描述相同的問題:有兩個(gè)抽象類A和F以便F extends A和F提供一些額外的功能。 兩者都聲明了具體類應(yīng)實(shí)現(xiàn)的抽象方法m() 。 當(dāng)具體的類C聲明從C extends A到C extends F到C extends F時(shí),方法m()的調(diào)用應(yīng)更改,但類C不應(yīng)有其他更改。 從類A定義的方法p()調(diào)用方法m() 。 如何設(shè)計(jì)F ?

這是什么問題?

可以通過兩種明顯不同的方式來擴(kuò)展A :

  • F覆蓋m()使它混凝土在實(shí)施額外的功能m()并調(diào)用新的抽象方法,說mx()
  • F使用提供額外功能的版本覆蓋方法p() (在上面的示例中進(jìn)行過濾),并調(diào)用仍然抽象的方法m()

第一種方法不能滿足由具體類C實(shí)施的簽名應(yīng)保持相同的要求。 第二種方法將A的已經(jīng)實(shí)現(xiàn)的功能扔到垃圾桶上,并以不同的方式重新實(shí)現(xiàn)它。 在實(shí)踐中這是可能的,但是肯定會進(jìn)行一些復(fù)制/粘貼編程。 這是有問題的,讓我不解釋原因。

問題的根源

在工程中,當(dāng)我們面對這樣的問題時(shí),通常意味著問題或結(jié)構(gòu)沒有得到很好的描述,解決方案位于完全不同的區(qū)域中。 換句話說,有些假設(shè)驅(qū)動我們的思維方式是錯(cuò)誤的。 在這種情況下,問題在于我們假設(shè)抽象類提供了一個(gè)擴(kuò)展“ API”來對其進(jìn)行擴(kuò)展。 請注意,API不僅可以調(diào)用。 對于抽象類,擴(kuò)展該抽象類時(shí)要實(shí)現(xiàn)的API。 正如庫可以為不同的使用方式提供不同的API(Java 9 HTTP客戶端可以send()以及sendAsync() )抽象(實(shí)際上也是非抽象的)類也可以提供不同的擴(kuò)展方式用于不同的目的。

如果不修改A就無法編碼F達(dá)到我們的設(shè)計(jì)目標(biāo)。 我們需要一個(gè)A版本,該版本提供不同的API來創(chuàng)建具體的實(shí)現(xiàn),而另一個(gè)版本(不一定要是正交的)可以創(chuàng)建一個(gè)仍然抽象的擴(kuò)展。

在這種情況下,API之間的區(qū)別在于,具體實(shí)現(xiàn)的目標(biāo)是在調(diào)用鏈的末尾,而抽象擴(kuò)展要掛接到鏈的最后一個(gè)元素。 A的實(shí)現(xiàn)必須提供要掛接到調(diào)用鏈的最后一個(gè)元素上的API。 這已經(jīng)是解決方案。

我們在類F實(shí)現(xiàn)了方法ma() ,我們希望p()調(diào)用ma()而不是直接調(diào)用m() 。 修改A我們可以做到。 我們在A定義ma() ,然后從p()調(diào)用ma() p() 。 在A實(shí)現(xiàn)的ma()版本應(yīng)毫不費(fèi)力地調(diào)用m() ,以為A具體實(shí)現(xiàn)提供原始的“ API”。 F中的ma()實(shí)現(xiàn)包含額外的功能(在示例中為過濾),然后調(diào)用m() 。 這樣,任何具體的類都可以擴(kuò)展A或F并可以使用完全相同的簽名實(shí)現(xiàn)m() 。 我們還避免了復(fù)制/粘貼編碼,只是調(diào)用m()是在ma()的兩個(gè)版本中相同的代碼。

如果我們希望類F具有更多抽象類可擴(kuò)展性,則F::ma實(shí)現(xiàn)不應(yīng)直接調(diào)用m() ,而應(yīng)調(diào)用m()的新mf() m() 。 這樣,新的抽象類可以覆蓋mf()從而再次提供新功能并調(diào)用抽象m() 。

帶走

  • 對抽象類進(jìn)行編程非常復(fù)雜,有時(shí)很難清楚地了解誰在調(diào)用誰以及哪種實(shí)現(xiàn)。 如果您意識到這可能是一件復(fù)雜的事情,則可以克服這一挑戰(zhàn)。 記錄,可視化,討論可以幫助您的任何方式。
  • 當(dāng)您不能解決問題時(shí)(在示例中,如何對F進(jìn)行編碼),您應(yīng)該挑戰(zhàn)環(huán)境(我們隱式地認(rèn)為問題A的類A是不變的:“如何實(shí)現(xiàn)F ?”)。
  • 避免復(fù)制/粘貼編程。 (面食包含大量CH,使您的代碼變胖,動脈被阻塞,最后,應(yīng)用程序的心臟將停止跳動。)
  • 盡管在本文中沒有詳細(xì)介紹,但是請注意,抽象層次越深,要清楚地了解誰來呼叫誰就越困難(另請參見第1點(diǎn))。
    • 在https://github.com/verhas/abstractchain中找到示例演示應(yīng)用程序
    • 在https://github.com/verhas/javageci中找到具有這種模式的原始的,稍微復(fù)雜的應(yīng)用程序

    翻譯自: https://www.javacodegeeks.com/2019/06/extending-abstract-classes-with-abstract-classes-in-java.html

    總結(jié)

    以上是生活随笔為你收集整理的用Java中的抽象类扩展抽象类的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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