欧美日韩不卡一区二区三区,www.蜜臀.com,高清国产一区二区三区四区五区,欧美日韩三级视频,欧美性综合,精品国产91久久久久久,99a精品视频在线观看

java語(yǔ)言

java的繼承與組合的區(qū)別

時(shí)間:2025-01-29 00:53:31 偲穎 java語(yǔ)言 我要投稿
  • 相關(guān)推薦

java的繼承與組合的區(qū)別

  Java是一門面向?qū)ο蟮木幊陶Z(yǔ)言,不僅吸收了C++語(yǔ)言的各種優(yōu)點(diǎn),還摒棄了C++里難以理解的多繼承、指針等概念,因此Java語(yǔ)言具有功能強(qiáng)大和簡(jiǎn)單易用兩個(gè)特征。下面是小編精心整理的java的繼承與組合的區(qū)別,僅供參考,大家一起來(lái)看看吧。

  繼承和組合的概念

  在新類里簡(jiǎn)單地創(chuàng)建原有類的對(duì)象。我們把這種方法叫作“組合”,因?yàn)樾骂愑涩F(xiàn)有類的對(duì)象合并而成。我們只是簡(jiǎn)單地重復(fù)利用代碼的功能,而不是采用它的形式。

  第二種方法是創(chuàng)建一個(gè)新類,將其作為現(xiàn)有類的一個(gè)“類型”。我們可以原樣采取現(xiàn)有類的形式,并在其中加入新代碼,同時(shí)不會(huì)對(duì)現(xiàn)有的類產(chǎn)生影響。這種魔術(shù)般的行為叫作“繼承”(Inheritance),涉及的大多數(shù)工作都是由編譯器完成的。對(duì)于面向?qū)ο蟮某绦蛟O(shè)計(jì),“繼承”是最重要的基礎(chǔ)概念之一。對(duì)于組合和繼承這兩種方法,大多數(shù)語(yǔ)法和行為都是類似的(因?yàn)樗鼈兌家鶕?jù)現(xiàn)有的類型生成新類型)。

  使用場(chǎng)合:

  組合:各部件之間沒(méi)什么關(guān)系,只需要組合即可。like組裝電腦,需要new CPU(),new RAM(),new Disk()……

  演示代碼如下:

  public class Computer {

  public Computer() {

  CPU cpu=new CPU();

  RAM ram=new RAM();

  Disk disk=new Disk();

  }

  }

  class CPU{ }

  class RAM{ }

  class Disk{ }

  繼承:子類需要具有父類的功能,各子類之間有所差異。like Shape類作為基類,子類有Rectangle,CirCle,Triangle……

  演示代碼如下:

  class Shape {

  public void draw() {

  System.out.println("draw a shape");

  }

  public void erase() {

  System.out.println("erase");

  }

  }

  class Square extends Shape {

  @Override

  public void draw() {

  System.out.println("draw a Square");

  }

  public static void main(String[] args) {

  Square s = new Square();

  s.draw();

  s.erase();

  }

  }

  相比于組合,繼承有以下優(yōu)點(diǎn):

  1、在繼承中,子類自動(dòng)繼承父類的非私有成員(default類型視是否同包而定),在需要時(shí),可選擇直接使用或重寫。

  2、在繼承中,創(chuàng)建子類對(duì)象時(shí),無(wú)需創(chuàng)建父類對(duì)象,因?yàn)橄到y(tǒng)會(huì)自動(dòng)完成;而在組合中,創(chuàng)建組合類的對(duì)象時(shí),通常需要?jiǎng)?chuàng)建其所使用的所有類的對(duì)象。

  組合的優(yōu)點(diǎn):

  1、在組合中,組合類與調(diào)用類之間低耦合;而在繼承中子類與父類高耦合。

  2、可動(dòng)態(tài)組合。

  相關(guān)資料:

  雖然繼承是OOP的一大特性,但很多時(shí)候并不推薦使用,因?yàn)樗3H菀资菇Y(jié)構(gòu)復(fù)雜化,容易出錯(cuò)。因此,除非我們確信使用繼承會(huì)使程序效率最高,否則,不考慮使用它。

  當(dāng)Java 1.5引入注解,企業(yè)開(kāi)發(fā)者對(duì)簡(jiǎn)化EJB和其他企業(yè)產(chǎn)品開(kāi)發(fā)抱有很大期望。可以看一看同一時(shí)期的一篇文章用EJB 3.0簡(jiǎn)化企業(yè)Java開(kāi)發(fā)。

  然而從那時(shí)起,Java企業(yè)使用注解出現(xiàn)一些無(wú)法預(yù)料的后果和副作用,一些甚至到今天都沒(méi)有被注意到。幸運(yùn)的是,并非所有的副作用都沒(méi)有被注意到,來(lái)看一些例子,在StackOverflow標(biāo)題為“Why Java Annotations?”有很多有價(jià)值的評(píng)論,“Are Annotations Bad?”這篇文章有很棒的觀點(diǎn),還有“Magics Is Evil”,“Annotations…Good, Bad or Worse?”。

  java-programmer,并非所有的注解都相同:

  盡管上面許多討論都包含有價(jià)值的觀點(diǎn),但并不是所有注解都是相同的。

  這里有兩類注解,區(qū)別在于他們是否在運(yùn)行期影響程序。首先,說(shuō)一下無(wú)害的一類,它們并不會(huì)在運(yùn)行期對(duì)代碼產(chǎn)生任何影響;另一種是有害的一類,它們會(huì)修改運(yùn)行期行為。無(wú)害的注解包括@Deprecated, @Override, @SuppressWarnings, 等等。有害的注解包括@Entity, @Table, @PostConstruct, @ApplicationScoped,等等。

  在無(wú)害的注解中存在一小部分注解,它們非常實(shí)用。有一些提供在編譯期間(靜態(tài)檢查)捕獲錯(cuò)誤或提供安全保障。一些實(shí)用的注解包括:@Override, @NonNull/@Nullable 來(lái)自(Checker Framework), 等等。

  為什么有害的注解不好?我們定義了一些有害的注解,為什么要避免使用它們呢?

  想象一個(gè)標(biāo)準(zhǔn)的Java Data類擁有@PostConstruct方法。這個(gè)注解表示所標(biāo)注的方法應(yīng)該在對(duì)象創(chuàng)建好之后被調(diào)用。這個(gè)功能并不是由JVM處理,所以Date類隱式獲取未知的框架和容器,而自身語(yǔ)義上并沒(méi)有做任何事情。如果這些代碼并不運(yùn)行在任何容器中,而只是運(yùn)行在JVM中呢?這個(gè)注解大大降低了這個(gè)類的重用性。另外對(duì)于任何使用Date的地方進(jìn)行單元測(cè)試就變成了噩夢(mèng),因?yàn)槟惚仨毚_保每次都正確綁定post-construction,要模擬一個(gè)兼容的容器。這就有點(diǎn)可笑了,一個(gè)Date類需要一個(gè)容器來(lái)運(yùn)行,但這確實(shí)是有害的注解對(duì)類、方法和參數(shù)的影響。

  無(wú)可否認(rèn),業(yè)務(wù)邏輯往往復(fù)雜,需要更多依賴和關(guān)系,而不僅僅是一個(gè)簡(jiǎn)單的Date類。然而沒(méi)有理由在一個(gè)類中顯式或隱式地添加不必要的依賴或約束,有害的注解就是:依賴和約束。

  企業(yè)陷阱

  不幸的是有害的聲明在Java Enterprise 5大規(guī)模合法化。為了更正早期企業(yè)API的易用性問(wèn)題,注解用來(lái)隱藏系統(tǒng)中冗余的和難用的部分。新的JEE 5被稱贊為”輕量級(jí)”和”簡(jiǎn)單”,表面上看起來(lái)是這樣。但是一個(gè)微小的,同時(shí)也是至關(guān)重要的誤用蔓延開(kāi)來(lái)。

  @Statelesspublic class DocumentRepository { public Document getDocument(String title) {

  ...

  }

  ...

  }

  如果想要獲取一個(gè)Stateless EJB,“只需要”在類上聲明@Stateless注解。確實(shí),編寫這個(gè)類只需要只一點(diǎn)動(dòng)作,但是請(qǐng)注意這個(gè)類中有害的注解綁定了幾百頁(yè)的說(shuō)明文檔,而且只能在百萬(wàn)字節(jié)的應(yīng)用服務(wù)器(Application Server)上運(yùn)行。這又怎么能稱的上是”輕量級(jí)”呢。所以,這個(gè)注解僅僅是真正需要編寫的Java代碼的占位符而已,代碼仍需要以某種形式存在,F(xiàn)在只不過(guò)是隱藏在注解之下。

  不幸的是,這種變通方案稱為一種模式,現(xiàn)在有害的注解廣泛分布:JPA, CDI, Common Annotations, JAXB 等等。

  有害的注解有時(shí)會(huì)出現(xiàn)在錯(cuò)誤的地點(diǎn)

  因?yàn)樽⒔馔ǔW鳛殚_(kāi)發(fā)環(huán)境,有時(shí)有害的注解被當(dāng)做單一職責(zé)原則(Single Responsibility Principle)或關(guān)注點(diǎn)分離(Separation of Concerns)的最佳實(shí)踐。

  讓我們來(lái)考慮一下下面這個(gè)CDI例子:

  @ApplicationScopedpublic class DocumentFormatter {

  ...

  }

  上面的注解描述這個(gè)類應(yīng)該是一個(gè)CDI Bean,意味著它應(yīng)該只能由CDI實(shí)例化,并確保每個(gè)應(yīng)用中只有一個(gè)實(shí)例。

  這些信息并不屬于這個(gè)類。這個(gè)服務(wù)在功能上(無(wú)論什么方式)并不會(huì)對(duì)它在當(dāng)前應(yīng)用中的作用產(chǎn)生影響。這里有兩個(gè)明顯的關(guān)注點(diǎn)。

  一個(gè)JPA的簡(jiǎn)單例子:

  @Entity@Table("PERSON")public class Person {

  ...

  }

  問(wèn)題在于這種類往往是”領(lǐng)域?qū)ο?domain objects)”,它們直接將領(lǐng)域模型持久化。更糟的是,數(shù)據(jù)傳送對(duì)象(DTO)用來(lái)在對(duì)象之間傳送數(shù)據(jù),使得整個(gè)構(gòu)造變得脆弱,因?yàn)閷?duì)象間耦合過(guò)于緊密。不管怎樣,這是一種錯(cuò)誤的方式。

  所有的這些附加的功能和(或)信息應(yīng)該從這些類中分離出來(lái),但是它們卻悄悄混在一起,因?yàn)樗鼈儭敝徊贿^(guò)”是注解。

  有害的注解有時(shí)蔓延

  注解有時(shí)會(huì)傳染其他對(duì)象;仡櫳厦婺莻(gè)CDI Bean。每個(gè)使用它的對(duì)象,每個(gè)依賴它的對(duì)象現(xiàn)在都擁有一個(gè)CDI注解,否則依賴關(guān)系樹就不會(huì)構(gòu)建成功。

  @Entity注解也一樣。因?yàn)閷?duì)象之間的關(guān)系,其他對(duì)象也通過(guò)注解持久化,很快所有的持久化對(duì)象都會(huì)有這個(gè)注解。我們無(wú)法使用原生的第三方對(duì)象(除非序列化或包裝它們),我們無(wú)法使用其他持久化機(jī)制(比如用NoSQL DB存放對(duì)象)。

  這些注解使得這些對(duì)象無(wú)法復(fù)用。它們只能在一個(gè)嚴(yán)格的、受控制的、不透明的環(huán)境中使用,不能和任何東西整合。

  有什么替代品?

  是XML嗎?當(dāng)然不是,至少對(duì)于上面的例子來(lái)說(shuō)不是。

  Spring框架使用配置來(lái)管理對(duì)象,因此可以用XML當(dāng)做配置文件。然而,是否某個(gè)依賴需要在運(yùn)行期改變,而不通過(guò)重新編譯?如果不需要,那么很難說(shuō)配置應(yīng)該用另一門語(yǔ)言來(lái)表示,尤其重構(gòu)困難、測(cè)試?yán)щy、管理需要特殊工具。

  真正的替代品當(dāng)然是好的Java代碼,正確封裝并解耦的。是的,用代碼來(lái)管理對(duì)象,盡管有時(shí)被當(dāng)做樣板(boilerplate),但并不算糟糕。它帶來(lái)一些好處,比如讓代碼可讀、可調(diào)試、可重構(gòu)。只有那些長(zhǎng)片的、復(fù)雜的、冗余的樣板是糟糕的,比如“關(guān)于EJB 2.0”。但是解決方案并不是擺脫所有的樣板或用另一種語(yǔ)言隱藏樣板,而是簡(jiǎn)單干凈的架構(gòu),直接而不多余的信息,簡(jiǎn)單并合適的方式來(lái)面向?qū)ο蟆?/p>

  這也適用于JPA、Spring和其他東西。誤用注解來(lái)表示功能會(huì)發(fā)生Stcakoverflow上這個(gè)問(wèn)題“Arguments Against Annotations”,為什么不用已有的工具呢:比如Java語(yǔ)言本身和編譯器,來(lái)解決這類問(wèn)題,面向?qū)ο蠛蛙浖罴褜?shí)踐。

  如果注解在代碼運(yùn)行期加上了額外功能和約束,那它是有害的。這很糟糕,因?yàn)樗[藏了類或方法的切面,使之難懂、難復(fù)用、難重構(gòu)、難測(cè)試。

  不幸的是Java Enterprise不理睬Java開(kāi)發(fā)者社區(qū)中發(fā)對(duì)注解的聲音。所以企業(yè)級(jí)Java和其他”官方”框架更不可能重視這類問(wèn)題。

  至少我們可以持續(xù)關(guān)注有害的注解,如果可能盡量避免使用,編寫新的框架和軟件替換掉注解,不會(huì)出現(xiàn)有害注解所帶來(lái)的問(wèn)題。

【java的繼承與組合的區(qū)別】相關(guān)文章:

Java中的繼承與組合01-28

Java 繼承07-04

java的繼承總結(jié)08-06

Java與Java web的區(qū)別01-30

Java語(yǔ)言繼承的要點(diǎn)03-13

java繼承是什么06-11

Java語(yǔ)言的繼承結(jié)構(gòu)06-21

java語(yǔ)言的接口與繼承02-26

JavaScript與Java的區(qū)別03-30