国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

違例的限制

2019-11-18 13:19:43
字體:
來源:轉載
供稿:網友

  覆蓋一個方法時,只能產生已在方法的基礎類版本中定義的違例。這是一個重要的限制,因為它意味著與基礎類協同工作的代碼也會自動應用于從基礎類衍生的任何對象(當然,這屬于基本的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++實際上能夠在編譯期間檢查違例規范。
  
  我們必須熟悉到這一點:盡管違例規范是由編譯器在繼續期間強行遵守的,但違例規范并不屬于方法類型的一部分,后者僅包括了方法名以及自變量類型。因此,我們不可在違例規范的基礎上覆蓋方法。除此以外,盡管違例規范存在于一個方法的基礎類版本中,但并不表示它必須在方法的衍生類版本中存在。這與方法的“繼續”頗有不同(進行繼續時,基礎類中的方法也必須在衍生類中存在)。換言之,用于一個特定方法的“違例規范接口”可能在繼續和覆蓋時變得更“窄”,但它不會變得更“寬”——這與繼續時的類接口規則是正好相反的。

上一篇:捕獲所有違例

下一篇:創建自己的違例

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 如东县| 麻江县| 嘉荫县| 建平县| 红河县| 新余市| 兴安盟| 濮阳县| 唐河县| 新野县| 枣庄市| 凤山县| 涪陵区| 泾阳县| 临武县| 闵行区| 于田县| 方山县| 离岛区| 修水县| 湘潭市| 梅州市| 沐川县| 库车县| 香河县| 云浮市| 池州市| 宜黄县| 洛阳市| 星子县| 陵川县| 潼关县| 德兴市| 民勤县| 天峨县| 金沙县| 黔西| 华亭县| 万山特区| 罗江县| 临沭县|