日本国产亚洲-日本国产一区-日本国产一区二区三区-日本韩国欧美一区-日本韩国欧美在线-日本韩国欧美在线观看

當(dāng)前位置:雨林木風(fēng)下載站 > 技術(shù)開發(fā)教程 > 詳細(xì)頁面

合成 VS 繼承

合成 VS 繼承

更新時(shí)間:2020-02-09 文章作者:未知 信息來源:網(wǎng)絡(luò) 閱讀次數(shù):

昨兒看到一片比較 繼承與合成 的文章,不錯(cuò),翻譯出來大家共享。
內(nèi)容淺顯易懂,相信你也能從中有所收獲

BTW:翻譯的不好不要罵啊,嘿嘿。。。



合成 VS 繼承
關(guān)聯(lián)class的兩種基本途徑的對(duì)比
作者:Bill Venners
出處:http://www.artima.com/designtechniques/compoinh.html


摘要
這是我的Design Techniques的一部分,這里我分析了兩者的構(gòu)成(flexibility)和執(zhí)行牽連(performance implications),并且我針對(duì)兩者分別給出了指導(dǎo)方針。

正文
建立兩個(gè)類之間的關(guān)聯(lián)是軟件設(shè)計(jì)的眾多基本行為之一。繼承和合成是兩種基本的實(shí)現(xiàn)方法。盡管當(dāng)你使用繼承的時(shí)候JVM可以幫你做很多事情,但是你仍然可以使用合成來達(dá)到同樣的目的。本篇將比較這兩種途徑且給出使用它們的指導(dǎo)方針。
首先,介紹繼承和合成的背景

關(guān)于繼承
Class Fruit {......}
Class Apple extends Fruit {......}

Apple和Fruit通過extends關(guān)聯(lián)起來,蘋果是水果的一種。Fruit是Apple的supperclass,Apple是Fruit的subclass

關(guān)于合成
class Fruit {......}

class Apple {
private Fruit fruit = new Fruit();
//......
}

這里Apple和Fruit通過合成關(guān)聯(lián)起來,因?yàn)锳pple擁有一個(gè)引用Fruit對(duì)象的實(shí)例變量。Apple被稱為front-end class,F(xiàn)ruit被稱為 back-end class。

動(dòng)態(tài)綁定,多態(tài)和改變
當(dāng)你使用繼承來關(guān)聯(lián)兩個(gè)類的時(shí)候,你就可以利用動(dòng)態(tài)綁定和多態(tài)的好處了。

動(dòng)態(tài)綁定和多態(tài)最主要的好處之一是,他們可以幫助你更簡(jiǎn)單的修改代碼,包括添加新的子類。然而這些不能包括所有你需要改變的地方


修改superclass接口
在繼承關(guān)聯(lián)中,superclasses通常被稱為“脆弱的(fragile)”,因?yàn)閷?duì)superclass的一點(diǎn)點(diǎn)的改動(dòng)將波及到眾多應(yīng)用程序的代碼。說的更明白些,superclass最脆弱的是它的接口。如果superclass是well-designed的――良好的接口設(shè)計(jì),OO風(fēng)格的實(shí)現(xiàn),那么任何supperclass的實(shí)現(xiàn)的改變將不會(huì)有任何影響。如果修改superclass的接口,那么將波及到任何使用該superclass的地方和其subclass。
繼承有時(shí)被成為提供“弱封裝(week encapsulation)”,因?yàn)槟阒苯邮褂胹ubclass的地方都會(huì)受superclass接口的改變的影響。從某個(gè)角度來講,繼承是讓subclass重用superclass的代碼。


選擇合成?
繼承性的關(guān)聯(lián)很難來修改superclass的接口。合成則提供了easier-to-change的途徑。
通過繼承的代碼重用
class Fruit {
//返回切割后的份數(shù)
public int peel() {
System.out.println(“Peeling is appealing”);
return 1;
}

//將上面替換掉的新方法
public Peel peel() {
return new Peel(1);//另外一個(gè)類
}
}

class Apple extends Fruit {
}

class Example1 {
public static void main(String[] args) {
Apple apple = new Apple();
int pieces = apple.peel(); //這里受到影響
}
}

Example1中通過Apple來調(diào)用繼承自Fruit的peel()方法,但是當(dāng)我們需要將peel()的返回值從int修改為Peel的時(shí)候(上面紅色部分),問題出現(xiàn)了,由于類型的不匹配(int peel)造成Example1的代碼不能通過編譯,雖然Example1并沒有和Fruit有任何直接的關(guān)聯(lián),但還是受到了很大影響。

通過合成的代碼重用
合成通過在Apple中保持一個(gè)Fruit對(duì)象的引用,在Apple中聲明一個(gè)新的peel方法,內(nèi)部實(shí)現(xiàn)只是簡(jiǎn)單的調(diào)用Fruit的peel方法。

class Fruit {
//返回切割后的份數(shù)
public int peel() {
System.out.println(“Peeling is appealing”);
return 1;
}

//需求改變后,將上面方法修改后的新接口
public Peel peel() {
return new Peel(1);//另外一個(gè)類
}
}

class Apple {
private Fruit fruit = new Fruit();

public int peel() {
return fruit.peel();

//使用Fruit的新接口,用于取代上面一行代碼
Peel peel = fruit.peel();
return peel.getPeelCount();
}
}

class Example2 {
public static void main(String[] args) {
Apple apple = new Apple();
int pieces = apple.peel();//這里不會(huì)有任何影響
}
}

在合成實(shí)現(xiàn)方式中,subclass變?yōu)閒ront-end class,superclass變?yōu)閎ack-end class。使用繼承,subclass自動(dòng)繼承了superclass的non-private方法;使用合成,front-end class必須在自身的實(shí)現(xiàn)中明確的調(diào)用back-end class中的相應(yīng)的方法。這種直接調(diào)用有時(shí)被稱為“推進(jìn)(forwarding)”或“委派(delegating)”這個(gè)方法的調(diào)用到back-end對(duì)象。

合成比繼承提供了更強(qiáng)壯的在代碼重用方面的封裝,因?yàn)閎ack-end class的修改不會(huì)波及任何依賴front-end class的代碼。例如我們要將Fruit的peel方法返回值修改為Peel(上面紅色部分),同時(shí)你會(huì)看到Apple的peel方法有相應(yīng)的改變,這時(shí)對(duì)Fruit接口的修改將不會(huì)影響到Example2的代碼,

比較合成與繼承
幾點(diǎn)對(duì)比:
back-end class(合成)比superclass(繼承)更容易修改接口。就像前面舉例說明的那樣,back-end class接口的改變必將導(dǎo)致front-end class實(shí)現(xiàn)的改變,但不會(huì)影響到front-end class的接口,所以依賴front-end class的代碼將正常工作。作為對(duì)比,superclass接口的修改不僅波及subclass層,也會(huì)影響到所有直接使用superclass接口以及使用subclass接口的地方
front-end class(合成)比subclass(繼承)更容易修改接口。正像superclass是脆弱(fragile)的,而subclass是堅(jiān)硬(rigid)的。你不能只改變subclass的接口而不去確認(rèn)新接口是否和父類型(supertypes)兼容。例如,你不能在subclass中添加一個(gè)與superclass方法同樣特征但返回值類型不同的新方法。合成則允許你修改front-end class的接口,而不用關(guān)心back-class。
合成允許你延遲back-end objects的創(chuàng)建,直到他們被需要的時(shí)候才創(chuàng)建,在front-end object的生命期內(nèi)可以動(dòng)態(tài)的改變back-end objects。對(duì)于繼承來說,一旦subclass被創(chuàng)建了,你就可以通過subclass object來獲取superclass的某些資源了,在subclass生命期內(nèi)一直保持著superclass的對(duì)象,也就是說,subclass object一旦被創(chuàng)建,superclass就已知且不可改變了。
添加subclasses(繼承)比添加front-end class(合成)更容易。因?yàn)槔^承伴隨多態(tài)。如果你的一些代碼僅依賴superclass,那么不用任何修改,你就能夠使用一個(gè)新的subclass。對(duì)于合成來說就不可以,除非你使用帶有接口的合成(composition with interfaces)。合成和接口的共同使用將提供一個(gè)非常強(qiáng)大的設(shè)計(jì)工具。
同使用subclass中從繼承superclass來的方法實(shí)現(xiàn)相比,合成中的直接的方法調(diào)用委派經(jīng)常(often)有性能損耗。Often的意思是說,因?yàn)樾阅芤蕾嚤姸嘁蛩兀热鏙VM優(yōu)化并執(zhí)行程序的能力。
對(duì)于合成和繼承來說,修改任何class的實(shí)現(xiàn)都是簡(jiǎn)單的。實(shí)現(xiàn)改變引起的連鎖反映被保留在同一個(gè)class


在合成和繼承中作出選擇
怎么作出選擇呢?這里有一個(gè)指導(dǎo)方針來讓我們趨向合成與繼承中的其中一個(gè)


繼承是is-a的關(guān)系
主要是說,繼承應(yīng)該只被用在“subclass is-a superclass”的時(shí)候。在上面例子中,Apple is-a Fruit,所以我們傾向使用繼承。

當(dāng)你認(rèn)為已經(jīng)有一個(gè)is-a關(guān)系的時(shí)候,你需要問自己 一個(gè)非常重要的問題,那就是這個(gè)“is-a 關(guān)系”是否在應(yīng)用程序或代碼生命周期中保持不變的(constant)。舉例:當(dāng)Employee在某個(gè)時(shí)間段扮演的角色是Person的時(shí)候,你可能認(rèn)為 Employee is-a Person。如果Person被解雇會(huì)怎樣?如果Person即是Employee又是Supervisor會(huì)怎樣?這種暫時(shí)的is-a關(guān)系通常使用合成,而不是繼承。


不要僅僅為了得到代碼重用就使用繼承
如果你的確想重用代碼且沒有觀察到is-a關(guān)系,那么使用合成


不要僅僅為了獲取多態(tài)就使用繼承
如果你卻是想要多態(tài),但是沒有自然的is-a關(guān)系,那么使用帶有接口的合成(composition with interfaces),這將在下個(gè)月介紹。




:

溫馨提示:喜歡本站的話,請(qǐng)收藏一下本站!

本類教程下載

系統(tǒng)下載排行

主站蜘蛛池模板: 国产人成久久久精品 | 日日夜夜网站 | 99福利视频 | 欧美猛交lxxxxxxxxx | 91在线免费公开视频 | 日韩三级免费观看 | 亚洲欧美v国产一区二区 | 波多野结衣在线网站 | 中文偷拍视频在线观看 | 天天干b| 国产片最新大片免费看 | 噜噜噜福利视频在线观看 | 国产九九精品视频 | 激情五月宗合网 | 国产欧美日韩免费一区二区 | 亚洲欧美人成网站综合在线 | 国产欧美日韩高清专区ho | 久草在线免费资源站 | 日韩一品道 | 久久这里只有精品国产99 | 99国产精品私拍pans大尺度 | 久草热草 | 久久伊人亚洲 | 天天干天天爽天天操 | 美国一级特级毛片片aa视频 | 在线免费视频一区 | 一区二区三区波多野结衣 | 亚洲国产欧美目韩成人综合 | 国产中文在线观看 | 国产成人高清视频免费播放 | 欧美日韩不卡在线 | 夜夜想夜夜爽天天爱天天摸 | 在线视频国产网址你懂的在线视频 | 日日操夜夜骑 | 精品一区二区三区视频在线观看免 | 青青青青操 | 国产高清在线播放免费观看 | 亚洲视频一二 | 成人短视频视频在线观看网站 | 日本xx高清视频免费观看 | 亚洲 欧美 手机 在线观看 |