java中抽象类继承抽象类_用Java中的抽象类扩展抽象类
java中抽象類(lèi)繼承抽象類(lèi)
示例問(wèn)題
當(dāng)我創(chuàng)建Java :: Geci抽象類(lèi)AbstractFieldsGenerator和AbstractFilteredFieldsGenerator我遇到了一個(gè)不太復(fù)雜的設(shè)計(jì)問(wèn)題。 我想強(qiáng)調(diào)一下,這個(gè)問(wèn)題和設(shè)計(jì)對(duì)于某些人來(lái)說(shuō)似乎很明顯,但是在我最近與一位初級(jí)開(kāi)發(fā)人員(我的兒子Mihály的交談)中,我的文章比我的英語(yǔ)要好得多,意識(shí)到這個(gè)話(huà)題可能仍然有價(jià)值。
無(wú)論如何。 我有這兩個(gè)類(lèi),字段和過(guò)濾字段生成器。 第二堂課擴(kuò)展了第一堂課
abstract class AbstractFilteredFieldsGenerator extends AbstractFieldsGenerator {...添加額外的功能,同時(shí)應(yīng)為具體實(shí)現(xiàn)提供相同的簽名。 這是什么意思?
這些生成器使用反射幫助生成特定類(lèi)的代碼。 因此,他們處理的輸入信息是Class對(duì)象。 字段生成器類(lèi)具有一個(gè)抽象方法process() ,該方法將為每個(gè)字段調(diào)用。 它是從實(shí)現(xiàn)的方法中調(diào)用的,該方法遍歷字段并分別對(duì)每個(gè)字段進(jìn)行調(diào)用。 當(dāng)具體類(lèi)extends AbstractFieldsGenerator并由此實(shí)現(xiàn)此抽象方法時(shí),它將被調(diào)用。 當(dāng)更改相同的具體類(lèi)以使其extends AbstractFilteredFieldsGenerator ,將僅為過(guò)濾的方法調(diào)用具體方法。 我想要一個(gè)設(shè)計(jì),以便在具體課程中唯一需要更改的是更改名稱(chēng)。
問(wèn)題定義 類(lèi)
以更抽象的方式描述相同的問(wèn)題:有兩個(gè)抽象類(lèi)A和F以便F extends A和F提供一些額外的功能。 兩者都聲明了具體類(lèi)應(yīng)實(shí)現(xiàn)的抽象方法m() 。 當(dāng)具體的類(lèi)C聲明從C extends A到C extends F到C extends F時(shí),方法m()的調(diào)用應(yīng)更改,但類(lèi)C不應(yīng)進(jìn)行其他更改。 從類(lèi)A定義的方法p()調(diào)用方法m() 。 如何設(shè)計(jì)F ?
這是什么問(wèn)題?
可以通過(guò)兩種明顯不同的方式來(lái)擴(kuò)展A :
- F覆蓋m()使它混凝土在實(shí)施額外的功能m()并調(diào)用新的抽象方法,說(shuō)mx()
- F使用提供額外功能的版本覆蓋方法p() (在上面的示例中進(jìn)行過(guò)濾),并調(diào)用仍然抽象的方法m()
第一種方法不能滿(mǎn)足由具體類(lèi)C實(shí)施的簽名應(yīng)保持相同的要求。 第二種方法將A的已經(jīng)實(shí)現(xiàn)的功能扔給垃圾并以不同的方式重新實(shí)現(xiàn)它。 實(shí)際上,這是可能的,但是肯定會(huì)進(jìn)行一些復(fù)制/粘貼編程。 這是有問(wèn)題的,讓我不解釋原因。
問(wèn)題的根源
在工程中,當(dāng)我們面對(duì)這樣的問(wèn)題時(shí),通常意味著問(wèn)題或結(jié)構(gòu)沒(méi)有得到很好的描述,解決方案位于完全不同的區(qū)域中。 換句話(huà)說(shuō),有些假設(shè)驅(qū)動(dòng)我們的思維方式是錯(cuò)誤的。 在這種情況下,問(wèn)題在于我們假設(shè)抽象類(lèi)提供了一個(gè)擴(kuò)展“ API”來(lái)對(duì)其進(jìn)行擴(kuò)展。 請(qǐng)注意,API不僅可以調(diào)用。 對(duì)于抽象類(lèi),擴(kuò)展該抽象類(lèi)時(shí)要實(shí)現(xiàn)的API。 正如庫(kù)可以為使用不同的方式提供不同的API(Java 9 HTTP客戶(hù)端可以send()以及sendAsync() )一樣,抽象(實(shí)際上也是非抽象的)類(lèi)也可以提供不同的擴(kuò)展方式。用于不同的目的。
如果不修改A就無(wú)法編碼F達(dá)到我們的設(shè)計(jì)目標(biāo)。 我們需要一個(gè)A版本,該版本提供不同的API來(lái)創(chuàng)建具體的實(shí)現(xiàn),并提供另一個(gè)(不一定是正交/正交)來(lái)創(chuàng)建靜態(tài)抽象的擴(kuò)展。
在這種情況下,API之間的區(qū)別在于,具體實(shí)現(xiàn)的目標(biāo)是在調(diào)用鏈的末尾,而抽象擴(kuò)展則希望鉤在調(diào)用鏈的最后一個(gè)元素上。 A的實(shí)現(xiàn)必須提供要掛接到調(diào)用鏈的最后一個(gè)元素上的API。 這已經(jīng)是解決方案。
解
我們?cè)陬?lèi)F實(shí)現(xiàn)方法ma() ,我們希望p()調(diào)用我們的ma()而不是直接調(diào)用m() 。 修改A我們可以做到。 我們?cè)贏定義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)包含額外的功能(在示例中為過(guò)濾),然后調(diào)用m() 。 這樣,任何具體的類(lèi)都可以擴(kuò)展A或F并可以使用完全相同的簽名實(shí)現(xiàn)m() 。 除了調(diào)用m()是與ma()的兩個(gè)版本相同的代碼外,我們還避免了復(fù)制/粘貼編碼。
如果我們希望類(lèi)F具有更多抽象類(lèi)可擴(kuò)展性,則F::ma實(shí)現(xiàn)不應(yīng)直接調(diào)用m() ,而應(yīng)調(diào)用m()的新mf() m() 。 這樣,新的抽象類(lèi)可以覆蓋mf()從而再次提供新功能并調(diào)用抽象m() 。
帶走
- 在https://github.com/verhas/abstractchain中找到示例演示應(yīng)用程序
- 在https://github.com/verhas/javageci上找到具有這種模式的原始的,有點(diǎn)復(fù)雜的應(yīng)用程序
翻譯自: https://www.javacodegeeks.com/2019/06/extending-abstract-classes-with-abstract-classes-in-java.html
java中抽象類(lèi)繼承抽象類(lèi)
總結(jié)
以上是生活随笔為你收集整理的java中抽象类继承抽象类_用Java中的抽象类扩展抽象类的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 怎么修改qq绑定邮箱(怎么修改qq绑定邮
- 下一篇: javax线程池超时结束_没有Javax