แนวคิดของหลักการนี้ได้รับการแนะนำโดย Barbara Liskov ในการปราศรัยของการประชุมในปี 1987 และต่อมาได้ตีพิมพ์ในเอกสารร่วมกับ Jannette Wing ในปี 1994 defiต้นฉบับมีดังนี้:
ให้ q (x) เป็นคุณสมบัติที่พิสูจน์ได้บนอ็อบเจกต์ x ของประเภท T จากนั้น q (y) ควรสามารถพิสูจน์ได้สำหรับอ็อบเจ็กต์ y ประเภท S โดยที่ S เป็นประเภทย่อยของ T.
ต่อจากนั้น ด้วยการตีพิมพ์หลักการ SOLID ของ Robert C. Martin ในหนังสือ Agile Software Development, Principles, Patterns, and Practices ของเขา และตีพิมพ์ซ้ำในหนังสือ Agile Principles, Patterns, and Practices in C# เวอร์ชัน C# defiกลายเป็นที่รู้จักในชื่อหลักการทดแทนของลิสคอฟ
สิ่งนี้นำเราไปสู่ defiข้อมูลที่ได้รับจาก Robert C. Martin: ต้องเปลี่ยนประเภทย่อยด้วยประเภทพื้นฐาน
คลาสรถ {
ฟังก์ชัน startEngine () {
// ฟังก์ชันสตาร์ทเครื่องยนต์เริ่มต้น
}
ฟังก์ชันเร่ง () {
// ฟังก์ชันการเร่งความเร็วเริ่มต้น
}
}
ระบุคลาสยานพาหนะ - อาจเป็นนามธรรม - และการใช้งานสองแบบ:
class Car ขยายยานพาหนะ {
ฟังก์ชัน startEngine () {
$ this-> EngagementIgnition ();
ผู้ปกครอง :: startEngine ();
}
ฟังก์ชันส่วนตัว EngagementIgnition () {
// ขั้นตอนการจุดระเบิด
}
}
คลาส ElectricBus ขยายยานพาหนะ {
ฟังก์ชันเร่ง () {
$ this-> เพิ่มแรงดันไฟฟ้า ();
$ this-> connectIndividualEngines ();
}
ฟังก์ชั่นส่วนตัวเพิ่มแรงดันไฟฟ้า () {
// ลอจิกไฟฟ้า
}
ฟังก์ชั่นส่วนตัว connectIndividualEngines () {
// ตรรกะการเชื่อมต่อ
}
}
คลาสไดร์เวอร์ {
function go (Vehicle $ v) {
$ v-> startEngine ();
$ v-> เร่ง ();
}
}
ซึ่งนำเราไปสู่การใช้งาน Template Method Design Pattern อย่างง่ายๆเหมือนที่เราใช้ใน OCP
คุณอาจสนใจหลักการ SOLID ที่สอง: https: //bloginnovazione.th / open-closed-second-solid-principle / 3906 /
จากประสบการณ์ก่อนหน้านี้ของเราเกี่ยวกับหลักการเปิด / ปิดเราสามารถสรุปได้ว่าหลักการแทนที่ Liskov เกี่ยวข้องอย่างใกล้ชิดกับ OCP ในความเป็นจริง "การละเมิด LSP เป็นการละเมิด OCP แบบแฝง" (Robert C. Martin) และรูปแบบวิธีการออกแบบเทมเพลตเป็นตัวอย่างคลาสสิกของการเคารพและการใช้งาน LSP ซึ่งจะเป็นหนึ่งในวิธีแก้ปัญหา ด้วย OCP
คลาสสี่เหลี่ยมผืนผ้า {
ส่วนตัว $ topLeft;
ความกว้าง $ ส่วนตัว;
ส่วนตัว $ สูง;
ฟังก์ชันสาธารณะ setHeight ($ height) {
$ this-> height = $ height;
}
ฟังก์ชันสาธารณะ getHeight () {
กลับ $ this-> height;
}
ฟังก์ชันสาธารณะ setWidth ($ width) {
$ this-> width = $ width;
}
ฟังก์ชันสาธารณะ getWidth () {
คืนค่า $ this-> width;
}
}
เริ่มจากรูปทรงเรขาคณิตพื้นฐานสี่เหลี่ยมผืนผ้า มันเป็นเพียงออบเจ็กต์ข้อมูลธรรมดาที่มีตัวตั้งค่าและตัวรับสำหรับความกว้างและความสูง ลองนึกภาพว่าแอปพลิเคชันของเราใช้งานได้และมีการปรับใช้กับลูกค้าหลายรายแล้ว ตอนนี้พวกเขาต้องการคุณสมบัติใหม่ พวกเขาต้องสามารถจัดการสี่เหลี่ยมได้
ในชีวิตจริงในรูปทรงเรขาคณิตสี่เหลี่ยมจัตุรัสคือรูปทรงเฉพาะของสี่เหลี่ยมผืนผ้า เราสามารถลองใช้คลาส Square ที่ขยายคลาส Rectangle มักกล่าวกันว่าคลาสลูกเป็นคลาสแม่และนิพจน์นี้ยังสอดคล้องกับ LSP อย่างน้อยก็ในตอนแรก
class Square ขยาย Rectangle {
ฟังก์ชันสาธารณะ setHeight ($ value) {
$ this-> width = $ value;
$ this-> height = $ value;
}
ฟังก์ชันสาธารณะ setWidth ($ value) {
$ this-> width = $ value;
$ this-> height = $ value;
}
}
สี่เหลี่ยมจัตุรัสคือสี่เหลี่ยมผืนผ้าที่มีความกว้างและความสูงเท่ากันและเราสามารถใช้งานแปลก ๆ ได้เหมือนในตัวอย่างก่อนหน้านี้ เราสามารถแทนที่ตัวตั้งค่าทั้งสองเพื่อกำหนดทั้งความสูงและความกว้าง แต่สิ่งนี้จะส่งผลต่อรหัสไคลเอนต์อย่างไร?
คลาสไคลเอนต์ {
function areaVerifier (สี่เหลี่ยมผืนผ้า $ r) {
$ r-> setWidth (5);
$ r-> setHeight (4);
ถ้า ($ r-> area ()! = 20) {
โยนข้อยกเว้นใหม่ ('พื้นที่ไม่ดี!');
}
กลับจริง
}
}
พื้นที่ฟังก์ชัน () {
ส่งคืน $ this-> width * $ this-> height;
}
เห็นได้ชัดว่าเราได้เพิ่มวิธีการข้างต้นในคลาส Rectangle ของเราเพื่อให้มีพื้นที่
คลาส LspTest ขยาย PHPUnit_Framework_TestCase {
ฟังก์ชัน testRectangleArea () {
$ r = สี่เหลี่ยมผืนผ้าใหม่ ();
$ c = ลูกค้าใหม่ ();
$ this-> assertTrue ($ c-> areaVerifier ($ r));
}
}
และเราได้สร้างการทดสอบอย่างง่ายโดยส่งวัตถุสี่เหลี่ยมผืนผ้าเปล่าไปยังตัวตรวจสอบพื้นที่และการทดสอบก็ผ่าน ถ้าคลาสของเราคือ Square defiเสร็จสิ้นอย่างถูกต้อง การส่งไปยัง areaVerifier() ของไคลเอ็นต์ไม่ควรทำให้ฟังก์ชันการทำงานเสียหาย ท้ายที่สุดแล้ว สี่เหลี่ยมจัตุรัสก็คือสี่เหลี่ยมผืนผ้าในความหมายทางคณิตศาสตร์ทุกประการ แต่มันเป็นชั้นเรียนของเราหรือไม่?
ฟังก์ชัน testSquareArea () {
$ r = สแควร์ใหม่ ();
$ c = ลูกค้าใหม่ ();
$ this-> assertTrue ($ c-> areaVerifier ($ r));
}
ดังนั้นคลาส Square ของเราจึงไม่ใช่สี่เหลี่ยมผืนผ้า มันฝ่าฝืนกฎแห่งเรขาคณิต มันล้มเหลวและละเมิดหลักการทดแทน Liskov.
Ercole Palmeri
การพัฒนาทักษะยนต์ปรับผ่านการระบายสีจะช่วยเตรียมเด็กๆ ให้พร้อมสำหรับทักษะที่ซับซ้อนมากขึ้น เช่น การเขียน หากต้องการสี...
ภาคกองทัพเรือเป็นมหาอำนาจทางเศรษฐกิจระดับโลกอย่างแท้จริง ซึ่งได้มุ่งหน้าสู่ตลาดมูลค่า 150 พันล้าน...
เมื่อวันจันทร์ที่แล้ว Financial Times ได้ประกาศข้อตกลงกับ OpenAI FT อนุญาติให้ทำข่าวระดับโลก...
ผู้คนนับล้านชำระค่าบริการสตรีมมิ่ง โดยจ่ายค่าธรรมเนียมการสมัครสมาชิกรายเดือน เป็นความเห็นทั่วไปที่คุณ...