refacforing

重構 - 改善既有程式的設計 - Deal with Generalization

這篇文章討論《重構 - 改善既有程式的設計》裡的第十一章 - Deal with Generalization

主要會討論程式碼的壞味道中 沒有被提及的重構方法裡面有關於 如何處理繼承關係 的內容

圖片以及程式碼來源自重構 - 改善既有程式的設計

如何處理繼承關係

Pull Up Field

把欄位提到superClass

Pull Up Method

把方法提到superClass

Pull Up Constructor

把會重複使用的建構子放到superClass

Extract Class

你可以用Single Responsibility Principle簡單的判斷一個類別的責任是不是太多 是的話就拆分成兩個類別

Extract Subclass

當你發現你這個類別的某些feature只被部分的instance使用 那就可以考慮一個SubClass

Extract Superclass

把subClass不需要的函式跟變數丟回給SuperClass

Extract Interface

很多個客戶都只用一個類別的某些方法們 或是兩個類別有某些方法相同 就可以把這某些方法給提煉出來

Collapse Hierarchy

把用不到的抽象類別移除

Form Template Method

兩個subClass有相似的演算法結構 就用Template method

Replace Inheritance with Delegation

繼承往往是造成過度親密的原因 因為subClass對superClass的瞭解總是超出預期 你可以用delegation來減少兩者的依賴

Replace Delegation with Inheritance

Replace Inheritance with Delegation的反向

Alt text

奇怪了 我們不是一直在鼓吹復合優先於繼承嗎 什麼情況才應該用繼承重構呢

來看個例子

我們有一個可愛的Person

class Person { 
  String _name;
  public String getName() { 
    return _name;
  }
  public void setName(String arg) {
    _name = arg; 
  }
  public String getLastName() {
    return _name.substring(_name.lastIndexOf(' ')+1);
  } 
}

還有一個Employee 使用了復合來delegate Person

class Employee {
  Person _person = new Person();
  public String getName() { 
    return _person.getName();
  }
  public void setName(String arg) {
    _person.setName(arg); 
  }
  public String toString () {
    return "Emp: " + _person.getLastName();
  } 
}

既然你幾乎每個函式都是直接去問Person 那不如直接繼承吧

class Employee extends Person {
  @Override public String toString() {
    return "Emp: " + getLastName();
  }
}