Fragile Base Classes Problem

新增 Base Class 的 method

因為增加 base class 的 method,其 method 的名稱跟,subclass 早已存在的 method 撞名。其實代表的行為/實作可能完全不一樣,但是因為剛好符合 method override 的架構,所以語法上沒有錯誤,編譯無痛通過。於是就會在 runtime 上,出現難以追踪/難以發現的邏輯錯誤。

第一版 Animal (先用 C++ 演譯)
struct Animal // V1
{
};

struct ElectricEel // 電鰻
{
  virtual int power() // 電鰻單次發電量
  {
    return 1000000; // 100KJ
  }
};
升級成第二版,新增健康吃飯功能
struct Animal // 
{
  virtual int power()
  {      
    return AnimalBMR(); // 基礎代謝熱量()
  }

  bool EatTooMuch(){
    return (power() > eaten()); // 電鰻表示: 
  }
};
Unexpected result
Animal* eel = new ElectricEel();
eel->EatTooMuch(); // 永遠吃不夠

修改 Base Class 的 method

因為修改 base class 的 method 實作,導致依懶 base class 實作內容的 subclass,繼續期待 base class 是以舊的方式表現行為,而出現無法感知的非預期的邏輯錯誤。

第一版,Animal 的 Say methods 都是單純 printf
struct Animal // V1
{
  virtual void say(){
    printf("Wowwww!");
  }
  
  virtual void layDownToSay() {
    printf("mm Wow");
  };  
};

struct Cat : public Animal
{    
  virtual void say(){
    layDownToSay();
  }
}; // Cat 想要躺下來叫,就 call  Animal::layDownToSay
第二版Animal 的 layDownToSay 回 call say()
struct Animal // V2
{
  virtual void say(){
    printf("Wowwww!");
  }
  
  virtual void layDownToSay() {
    say(); // 作者覺得躺下來叫的功能太廢了
            // 先 deprecated 並回 call say();
  };  
};
Initife loop
Animal* cat= new Cat();
cat->say(); // 導致躺下來叫->普通叫->躺下來叫->普通叫->... 無窮迴圈

Scala 的 override modifier

Scala 中加上 override modifier 的好處,可以改善(不是根除)第一種狀況。Scala 的 override modifier 寫法規定有三

  1. 最上層的 method,不能加 override modifier
  2. 沒有 implementation 的 method 稱之 abstract method。在 override 此 method 時,override modifier 可加可不加。

    Scala 推薦 【Always 都加上 override modifier。】

  3. 有 implementation 的 method 稱之 concrete method。在 override concrete method 時,一定要加上 override modifier

若 subclass 自己早已實作了 method X,則這個 method 的前面一定不能有 override modifier。所以當 base class 新增了同名的且含有了實作 method X,Compiler 則會 complains 說【某個 subclass 的 method X ,沒有加 override modifier。】來提醒 Fragile 的情況可能發生。

若 superclass 早有了 method X,則 subclass 不知情地加上了自己實作的 method X,subclass client 以為自己沒用到 superclass 的版本,於是就不會加上 override modifier。Compiler 此時也會 complains【某 subclass 的 method X 沒有加上 override modifier 哦。】

Reference:

http://en.wikipedia.org/wiki/Fragile_base_class
http://c2.com/cgi/wiki?FragileBaseClassProblem
http://www.artima.com/pins1ed/composition-and-inheritance.html#10.8

comments powered by Disqus