superclass 中的某个函数只与部分(而非全部)subclasses 有关。
将这个函数移到相关的那些subclasses 去。
动机(Motivation)
Push Down Method 恰恰相反于 Pull Up Method 。当我有必要把某些行为从superclass 移至特定的subclass 时,我就使用Push Down Method,它通常也只在这种时候有用。使用Extract Subclass 之后你可能会需要它。
作法(Mechanics)
· | 在所有subclass 中声明该函数,将superclass 中的函数本体拷贝到每一个subclass 函数中。 |
Ø | 你可能需要将superclass 的某些值域声明为protected,让subclass 函数也能够访问它们。如果日后你也想把这些值域下移到subclasses , 通常就可以那么做;否则应该使用superclass 提供的访问函数(accessors)。如果访问函数并非public ,你得将它声明为protected 。 |
· | 删除superclass 中的函数。 |
Ø | 你可能必须修改调用端的某些变量声明或参数声明,以便能够使用subclass 。 |
Ø | 如果有必要通过一个superclass 对象访问该函数,或如果你不想把该函数从任何subclass 中移除,或如果superclass 是抽象类,那么你就可以在superclass 中把该函数声明为抽象函数。 |
· | 编译,测试。 |
· | 将该函数从所有不需要它的那些subclasses 中删掉。 |
· | 编译,测试。 |
范例:(Example)
我以Customer「表示「顾客」,它有两个subclass :表示「普通顾客」的RegularCustomer 和表示「贵宾」PreferredCustomer。
两个subclass 都有一个createBill() 函数,并且代码完全一样:
void createBill (date Date) {
double chargeAmount = charge (lastBillDate, date);
addBill (date, charge);
}
但我不能直接把这个函数上移到superclass,因为各个subclass 的chargeFor() 函数并不相同。我必须先在superclass 中声明chargeFor() 抽象函数:
class Customer...
abstract double chargeFor(date start, date end)
然后,我就可以将createBill() 函数从其中一个subclass 拷贝到superclass。拷贝完之后应该编译,然后移除那个subclass 的createBill() 函数,然后编译并测试。 随后再移除另一个subclass 的createBill() 函数,再次编译并测试: