インタフェイスの事後条件と多様性について
オブジェクト指向入門第二版発売を記念してちょっと書いておく。
例えばレンタルビデオ店で通常会員とゴールド会員がいて、とあるビデオ(とりあえずダイハードにしておくか)の料金を計算する場合
と言うクラスやインタフェイスだったとする(リアルではこう言う設計はしないが例示なので勘弁してくれ)
public interface Customer {
int getDieHardPrice();
}public class NormalCustomer implements Customer {
public int getDieHardPrice() {
return 500;
}}
public class GoldCustomer implements Customer {
public int getDieHardPrice() {
return 300;
}}
そのレンタルビデオ店では10周年記念で割引の適用となり総額で200円の割引となったと仮定しよう。
そうした場合
上記のように実装したと仮定する。
public int getTotalPrice(int customerNo) {
Customer customer = CustomerFactory.create(customerNo);
int getPrice = customer.getDieHardPrice();
return getPrice - 200;
}
この店はダイハードしか置いてないという流行りそうもない前提付きだ。
ここでそこの店主は思いつき大好き人間なので10周年なのだから入会してくれた人は
特別会員にしようと言う話になって
ダイハードの料金を100円で良いとした場合に新たなクラスを作ると
ん?なんかおかしくないか?
public class VipCustomer implements Customer {public int getDieHardPrice() {
return 100;
}}
そもそも総額から200円の割引が適用されるのだからダイハードの価格が100円だとすると
客がダイハードを借りると店が客に100円支払うことになる。
とするとインタフェイスのgetDieHardPriceの事後条件は
通常会員とゴールド会員を元にインタフェイス抽出した場合には最も弱い条件である300円以上であるが適用される。
だから特別会員が現れた段階でインタフェイスの事後条件を破ってしまっているから
それを用いているクラスに影響が出るかもしれないと言うことだ。
インタフェイスを抽出して多様性を実現できる状態にすると言うことは
インタフェイスの事後条件を明確化しておかなければ仕様として破綻する可能性があると言うことだ。
getTotalPriceのテストケースがザルでなければ大丈夫そうだけどね。