<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>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # 9.5 異常的限制 覆蓋一個方法時,只能產生已在方法的基類版本中定義的異常。這是一個重要的限制,因為它意味著與基類協同工作的代碼也會自動應用于從基類派生的任何對象(當然,這屬于基本的OOP概念),其中包括異常。 下面這個例子演示了強加在異常身上的限制類型(在編譯期): ``` //: StormyInning.java // Overridden methods may throw only the // exceptions specified in their base-class // versions, or exceptions derived from the // base-class exceptions. class BaseballException extends Exception {} class Foul extends BaseballException {} class Strike extends BaseballException {} abstract class Inning { Inning() throws BaseballException {} void event () throws BaseballException { // Doesn't actually have to throw anything } abstract void atBat() throws Strike, Foul; void walk() {} // Throws nothing } class StormException extends Exception {} class RainedOut extends StormException {} class PopFoul extends Foul {} interface Storm { void event() throws RainedOut; void rainHard() throws RainedOut; } public class StormyInning extends Inning implements Storm { // OK to add new exceptions for constructors, // but you must deal with the base constructor // exceptions: StormyInning() throws RainedOut, BaseballException {} StormyInning(String s) throws Foul, BaseballException {} // Regular methods must conform to base class: //! void walk() throws PopFoul {} //Compile error // Interface CANNOT add exceptions to existing // methods from the base class: //! public void event() throws RainedOut {} // If the method doesn't already exist in the // base class, the exception is OK: public void rainHard() throws RainedOut {} // You can choose to not throw any exceptions, // even if base version does: public void event() {} // Overridden methods can throw // inherited exceptions: void atBat() throws PopFoul {} public static void main(String[] args) { try { StormyInning si = new StormyInning(); si.atBat(); } catch(PopFoul e) { } catch(RainedOut e) { } catch(BaseballException e) {} // Strike not thrown in derived version. try { // What happens if you upcast? Inning i = new StormyInning(); i.atBat(); // You must catch the exceptions from the // base-class version of the method: } catch(Strike e) { } catch(Foul e) { } catch(RainedOut e) { } catch(BaseballException e) {} } } ///:~ ``` 在`Inning`中,可以看到無論構造器還是`event()`方法都指出自己會“拋”出一個異常,但它們實際上沒有那樣做。這是合法的,因為它允許我們強迫用戶捕獲可能在覆蓋過的event()版本里添加的任何異常。同樣的道理也適用于`abstract`方法,就象在`atBat()`里展示的那樣。 `interface Storm`非常有趣,因為它包含了在`Incoming`中定義的一個方法——`event()`,以及不是在其中定義的一個方法。這兩個方法都會“拋”出一個新的異常類型:`RainedOut`。當執行到`StormyInning extends`和`implements Storm`的時候,可以看到`Storm`中的`event()`方法不能改變`Inning`中的`event()`的異常接口。同樣地,這種設計是十分合理的;否則的話,當我們操作基類時,便根本無法知道自己捕獲的是否正確的東西。當然,假如`interface`中定義的一個方法不在基類里,比如`rainHard()`,它產生異常時就沒什么問題。 對異常的限制并不適用于構造器。在`StormyInning`中,我們可看到一個構造器能夠“拋”出它希望的任何東西,無論基類構造器“拋”出什么。然而,由于必須堅持按某種方式調用基類構造器(在這里,會自動調用默認構造器),所以派生類構造器必須在自己的異常規范中聲明所有基類構造器異常。 `StormyInning.walk()`不會編譯的原因是它“拋”出了一個異常,而`Inning.walk()`卻不會“拋”出。若允許這種情況發生,就可讓自己的代碼調用`Inning.walk()`,而且它不必控制任何異常。但在以后替換從`Inning`派生的一個類的對象時,異常就會“拋”出,造成代碼執行的中斷。通過強迫派生類方法遵守基類方法的異常規范,對象的替換可保持連貫性。 覆蓋過的`event()`方法向我們顯示出一個方法的派生類版本可以不產生任何異常——即便基類版本要產生異常。同樣地,這樣做是必要的,因為它不會中斷那些已假定基類版本會產生異常的代碼。差不多的道理亦適用于`atBat()`,它會“拋”出`PopFoul`——從`Foul`派生出來的一個異常,而`Foul`異常是由`atBat()`的基類版本產生的。這樣一來,假如有人在自己的代碼里操作`Inning`,同時調用了`atBat()`,就必須捕獲`Foul`異常。由于`PopFoul`是從`Foul`派生的,所以異常控制器(模塊)也會捕獲`PopFoul`。 最后一個有趣的地方在`main()`內部。在這個地方,假如我們明確操作一個`StormyInning`對象,編譯器就會強迫我們只捕獲特定于那個類的異常。但假如我們向上轉換到基類型,編譯器就會強迫我們捕獲針對基類的異常。通過所有這些限制,異常控制代碼的“健壯”程度獲得了大幅度改善(注釋③)。 ③:ANSI/ISO C++施加了類似的限制,要求派生方法異常與基類方法拋出的異常相同,或者從后者派生。在這種情況下,C++實際上能夠在編譯期間檢查異常規范。 我們必須認識到這一點:盡管異常規范是由編譯器在繼承期間強行遵守的,但異常規范并不屬于方法類型的一部分,后者僅包括了方法名以及參數類型。因此,我們不可在異常規范的基礎上覆蓋方法。除此以外,盡管異常規范存在于一個方法的基類版本中,但并不表示它必須在方法的派生類版本中存在。這與方法的“繼承”頗有不同(進行繼承時,基類中的方法也必須在派生類中存在)。換言之,用于一個特定方法的“異常規范接口”可能在繼承和覆蓋時變得更“窄”,但它不會變得更“寬”——這與繼承時的類接口規則是正好相反的。
                  <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>

                              哎呀哎呀视频在线观看