Subtypes must be substitutable for their base types. 派生類型必須可以替換它的基類型。 復(fù)制代碼 在面向?qū)ο缶幊汤?,繼承提供了一個(gè)機(jī)制讓子類和共享基類的代碼,這是通過在基類型里封裝通用的數(shù)據(jù)和行為來實(shí)現(xiàn)的,然后已經(jīng)及類型來聲明更詳細(xì)的子類型,為了應(yīng)用里氏替換原則,繼承子類型需要在語義上等價(jià)于基類型里的期望行為。
為了來更好的理解,請參考如下代碼: 代碼如下: function Vehicle(my) { var my = my || {}; my.speed = 0; my.running = false;
上述代碼我們定義了一個(gè)Vehicle函數(shù),其構(gòu)造函數(shù)為vehicle對象提供了一些基本的操作,我們來想想如果當(dāng)前函數(shù)當(dāng)前正運(yùn)行在服務(wù)客戶的產(chǎn)品環(huán)境上,如果現(xiàn)在需要添加一個(gè)新的構(gòu)造函數(shù)來實(shí)現(xiàn)加快移動(dòng)的vehicle。思考以后,我們寫出了如下代碼: 代碼如下: function FastVehicle(my) { var my = my || {};
var that = new Vehicle(my); that.accelerate = function() { my.speed += 3; }; return that; }
在瀏覽器的控制臺(tái)我們都測試了,所有的功能都是我們的預(yù)期,沒有問題,F(xiàn)astVehicle的速度增快了3倍,而且繼承他的方法也是按照我們的預(yù)期工作。此后,我們開始部署這個(gè)新版本的類庫到產(chǎn)品環(huán)境上,可是我們卻接到了新的構(gòu)造函數(shù)導(dǎo)致現(xiàn)有的代碼不能支持執(zhí)行了,下面的代碼段揭示了這個(gè)問題: 代碼如下: var maneuver = function(vehicle) { write(vehicle.state()); vehicle.start(); write(vehicle.state()); vehicle.accelerate(); write(vehicle.state()); write(vehicle.speed()); vehicle.decelerate(); write(vehicle.speed()); if (vehicle.state() != "idle") { throw "The vehicle is still moving!"; } vehicle.stop(); write(vehicle.state()); };
根據(jù)上面的代碼,我們看到拋出的異常是“The vehicle is still moving!”,這是因?yàn)閷戇@段代碼的作者一直認(rèn)為加速(accelerate)和減速(decelerate)的數(shù)字是一樣的。但FastVehicle的代碼和Vehicle的代碼并不是完全能夠替換掉的。因此,F(xiàn)astVehicle違反了里氏替換原則。