<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                ## [抽象類和方法](https://lingcoder.gitee.io/onjava8/#/book/10-Interfaces?id=%e6%8a%bd%e8%b1%a1%e7%b1%bb%e5%92%8c%e6%96%b9%e6%b3%95) 在上一章的樂器例子中,基類**Instrument**中的方法往往是“啞”方法。如果調用了這些方法,就會出現一些錯誤。這是因為接口的目的是為它的派生類創建一個通用接口。 在那些例子中,創建這個通用接口的唯一理由是,不同的子類可以用不同的方式表示此接口。通用接口建立了一個基本形式,以此表達所有派生類的共同部分。另一種說法把**Instrument**稱為抽象基類,或簡稱抽象類。 對于像**Instrument**那樣的抽象類來說,它的對象幾乎總是沒有意義的。創建一個抽象類是為了通過通用接口操縱一系列類。因此,**Instrument**只是表示接口,不是具體實現,所以創建一個**Instrument**的對象毫無意義,我們可能希望阻止用戶這么做。通過讓**Instrument**所有的方法產生錯誤,就可以達到這個目的,但是這么做會延遲到運行時才能得知錯誤信息,并且需要用戶進行可靠、詳盡的測試。最好能在編譯時捕捉問題。 Java 提供了一個叫做*抽象方法*的機制,這個方法是不完整的:它只有聲明沒有方法體。下面是抽象方法的聲明語法: ~~~ abstract void f(); ~~~ 包含抽象方法的類叫做*抽象類*。如果一個類包含一個或多個抽象方法,那么類本身也必須限定為抽象的,否則,編譯器會報錯。 ~~~ // interface/Basic.java abstract class Basic { abstract void unimplemented(); } ~~~ 如果一個抽象類是不完整的,當試圖創建這個類的對象時,Java 會怎么做呢?它不會創建抽象類的對象,所以我們只會得到編譯器的錯誤信息。這樣保證了抽象類的純粹性,我們不用擔心誤用它。 ~~~ // interfaces/AttemptToUseBasic.java // {WillNotCompile} public class AttemptToUseBasic { Basic b = new Basic(); // error: Basic is abstract; cannot be instantiated } ~~~ 如果創建一個繼承抽象類的新類并為之創建對象,那么就必須為基類的所有抽象方法提供方法定義。如果不這么做(可以選擇不做),新類仍然是一個抽象類,編譯器會強制我們為新類加上**abstract**關鍵字。 ~~~ // interfaces/Basic2.java abstract class Basic2 extends Basic { int f() { return 111; } abstract void g() { // unimplemented() still not implemented } } ~~~ 可以將一個不包含任何抽象方法的類指明為**abstract**,在類中的抽象方法沒啥意義但想阻止創建類的對象時,這么做就很有用。 ~~~ // interfaces/AbstractWithoutAbstracts.java abstract class Basic3 { int f() { return 111; } // No abstract methods } public class AbstractWithoutAbstracts { // Basic3 b3 = new Basic3(); // error: Basic3 is abstract; cannot be instantiated } ~~~ 為了創建可初始化的類,就要繼承抽象類,并提供所有抽象方法的定義: ~~~ // interfaces/Instantiable.java abstract class Uninstantiable { abstract void f(); abstract int g(); } public class Instantiable extends Uninstantiable { @Override void f() { System.out.println("f()"); } @Override int g() { return 22; } public static void main(String[] args) { Uninstantiable ui = new Instantiable(); } } ~~~ 留意`@Override`的使用。沒有這個注解的話,如果你沒有定義相同的方法名或簽名,抽象機制會認為你沒有實現抽象方法從而產生編譯時錯誤。因此,你可能認為這里的`@Override`是多余的。但是,`@Override`還提示了這個方法被覆寫——我認為這是有用的,所以我會使用`@Override`,即使在沒有這個注解,編譯器告訴我錯誤的時候。 記住,事實上的訪問權限是“friendly”。你很快會看到接口自動將其方法指明為**public**。事實上,接口只允許**public**方法,如果不加訪問修飾符的話,接口的方法不是**friendly**而是**public**。然而,抽象類允許每件事: ~~~ // interfaces/AbstractAccess.java abstract class AbstractAccess { private void m1() {} // private abstract void m1a(); // illegal protected void m2() {} protected abstract void m2a(); void m3() {} abstract void m3a(); public void m4() {} public abstract void m4a(); } ~~~ **private abstract**被禁止了是有意義的,因為你不可能在**AbstractAccess**的任何子類中合法地定義它。 上一章的**Instrument**類可以很輕易地轉換為一個抽象類。只需要部分方法是**abstract**即可。將一個類指明為**abstract**并不強制類中的所有方法必須都是抽象方法。如下圖所示: ![類圖](https://lingcoder.gitee.io/onjava8/images/1562653648586.png) 下面是修改成使用抽象類和抽象方法的管弦樂器的例子: ~~~ // interfaces/music4/Music4.java // Abstract classes and methods // {java interfaces.music4.Music4} package interfaces.music4; import polymorphism.music.Note; abstract class Instrument { private int i; // Storage allocated for each public abstract void play(Note n); public String what() { return "Instrument"; } public abstract void adjust(); } class Wind extends Instrument { @Override public void play(Note n) { System.out.println("Wind.play() " + n); } @Override public String what() { return "Wind"; } @Override public void adjust() { System.out.println("Adjusting Wind"); } } class Percussion extends Instrument { @Override public void play(Note n) { System.out.println("Percussion.play() " + n); } @Override public String what() { return "Percussion"; } @Override public void adjust() { System.out.println("Adjusting Percussion"); } } class Stringed extends Instrument { @Override public void play(Note n) { System.out.println("Stringed.play() " + n); } @Override public String what() { return "Stringed"; } @Override public void adjust() { System.out.println("Adjusting Stringed"); } } class Brass extends Wind { @Override public void play(Note n) { System.out.println("Brass.play() " + n); } @Override public void adjust() { System.out.println("Adjusting Brass"); } } class Woodwind extends Wind { @Override public void play(Note n) { System.out.println("Woodwind.play() " + n); } @Override public String what() { return "Woodwind"; } } public class Music4 { // Doesn't care about type, so new types // added to system still work right: static void tune(Instrument i) { // ... i.play(Note.MIDDLE_C); } static void tuneAll(Instrument[] e) { for (Instrument i: e) { tune(i); } } public static void main(String[] args) { // Upcasting during addition to the array: Instrument[] orchestra = { new Wind(), new Percussion(), new Stringed(), new Brass(), new Woodwind() }; tuneAll(orchestra); } } ~~~ 輸出: ~~~ Wind.play() MIDDLE_C Percussion.play() MIDDLE_C Stringed.play() MIDDLE_C Brass.play() MIDDLE_C Woodwind.play() MIDDLE_C ~~~ 除了**Instrument**,基本沒區別。 創建抽象類和抽象方法是有幫助的,因為它們使得類的抽象性很明確,并能告知用戶和編譯器使用意圖。抽象類同時也是一種有用的重構工具,使用它們使得我們很容易地將沿著繼承層級結構上移公共方法。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看