สำรวจหลักการเปลี่ยนตัว Liskov
คำว่า SOLID เป็นคำย่อยอดนิยมที่ใช้เพื่ออ้างถึงชุดของหลักการ 5 ประการของสถาปัตยกรรมซอฟต์แวร์ ซึ่งรวมถึง: SRP (ความรับผิดชอบเดียว), เปิด / ปิด, การทดแทนของ Liskov, การแยกส่วนต่อประสานและการผกผันการพึ่งพา
LSP (Liskov Substitution Principle) เป็นหลักการพื้นฐานของ OOP และระบุว่าคลาสที่ได้รับควรจะสามารถขยายคลาสพื้นฐานได้โดยไม่ต้องเปลี่ยนพฤติกรรม กล่าวอีกนัยหนึ่งคลาสที่ได้รับควรสามารถเปลี่ยนได้สำหรับประเภทฐานกล่าวคือการอ้างอิงไปยังคลาสฐานควรสามารถแทนที่ด้วยคลาสที่ได้รับโดยไม่ส่งผลกระทบต่อพฤติกรรม หลักการทดแทน Liskov แสดงถึงการพิมพ์ย่อยเชิงพฤติกรรมที่ชัดเจนและได้รับการแนะนำโดย Barbara Liskov ในปี 2530
อ้างอิงจาก Barbara Liskov "สิ่งที่ต้องการในที่นี้คือคุณสมบัติการทดแทนต่อไปนี้: ถ้าสำหรับแต่ละอ็อบเจ็กต์ o1 ประเภท S มีอ็อบเจ็กต์ o2 ประเภท T สำหรับโปรแกรมทั้งหมดที่กำหนดไว้ในรูปของ T พฤติกรรมของ P จะไม่เปลี่ยนแปลงเมื่อ o1 ถูกแทนที่ด้วย o2 ดังนั้น S จะเป็นประเภทย่อยของ T "
ตัวอย่างคลาสสิกของการละเมิดหลักการเปลี่ยนตัว Liskov คือปัญหาสี่เหลี่ยมผืนผ้า - สี่เหลี่ยมจัตุรัส คลาส Square ขยายคลาส Rectangle และถือว่าความกว้างและความสูงเท่ากัน
พิจารณาชั้นเรียนต่อไปนี้ คลาส Rectangle ประกอบด้วยข้อมูลสองสมาชิก - ความกว้างและความสูง นอกจากนี้ยังมีคุณสมบัติสามประการ ได้แก่ ความสูงความกว้างและพื้นที่ ในขณะที่คุณสมบัติสองประการแรกตั้งค่าความสูงและความกว้างของรูปสี่เหลี่ยมผืนผ้าคุณสมบัติ Area มี getter ที่ส่งกลับพื้นที่ของสี่เหลี่ยมผืนผ้า
class Rectangle
{
protected int width;
protected int height;
public virtual int Width
{
get
{
return width;
}
set
{
width = value;
}
}
public virtual int Height
{
get
{
return height;
}
set
{
height = value;
}
}
public int Area
{
get
{
return height * width;
}
}
}
สี่เหลี่ยมจัตุรัสคือรูปสี่เหลี่ยมผืนผ้าประเภทหนึ่งที่ด้านข้างมีขนาดเท่ากันกล่าวคือความกว้างและความสูงของสี่เหลี่ยมจัตุรัสเท่ากัน
class Square : Rectangle
{
public override int Width
{
get
{
return width;
}
set
{
width = value;
height = value;
}
}
public override int Height
{
get
{
return width;
}
set
{
width = value;
height = value;
}
}
}
พิจารณาคลาสอื่นที่เรียกว่า ObjectFactory
class ObjectFactory
{
public static Rectangle GetRectangleInstance()
{
return new Square();
}
}
โปรดสังเกตว่าตัวตั้งค่าสำหรับคุณสมบัติความกว้างและความสูงในคลาส Square ถูกแทนที่และแก้ไขเพื่อให้แน่ใจว่าความสูงและความกว้างเท่ากัน ตอนนี้เรามาสร้างอินสแตนซ์ของคลาส Rectangle โดยใช้และตั้งค่าคุณสมบัติความสูงและความกว้าง
Rectangle s = ObjectFactory.GetRectangleInstance();
s.Height = 9;
s.Width = 8;
Console.WriteLine(s.Area);
ข้อมูลโค้ดด้านบนเมื่อดำเนินการจะแสดงค่า 64 ในคอนโซล ค่าที่คาดหวังคือ 72 เนื่องจากความกว้างและความสูงที่กล่าวถึงคือ 9 และ 8 ตามลำดับ นี่เป็นการละเมิดหลักการเปลี่ยนตัว Liskov ทั้งนี้เนื่องจากคลาส Square ที่ขยายคลาส Rectangle ได้ปรับเปลี่ยนพฤติกรรม เพื่อให้แน่ใจว่าจะไม่ละเมิดหลักการการทดแทน Liskov คลาส Square สามารถขยายคลาส Rectangle ได้ แต่ไม่ควรปรับเปลี่ยนพฤติกรรม พฤติกรรมได้รับการเปลี่ยนแปลงโดยการแก้ไขตัวตั้งค่าสำหรับคุณสมบัติทั้งความกว้างและความสูง ค่าของความสูงและความกว้างจะเหมือนกันหากเป็นรูปสี่เหลี่ยมจัตุรัส - ไม่ควรเหมือนกันหากเป็นสี่เหลี่ยมผืนผ้า
เราจะแก้ไขอย่างไรกล่าวคือมั่นใจว่าหลักการนี้จะไม่ละเมิด? คุณสามารถมีคลาสใหม่ที่เรียกว่า Quadrilateral และตรวจสอบให้แน่ใจว่าทั้งคลาส Rectangle และ Square ขยายคลาส Quadrilateral
public class Quadrilateral
{
public virtual int Height { get; set; }
public virtual int Width { get; set; }
public int Area
{
get
{
return Height * Width;
}
}
}
ตอนนี้ทั้งคลาส Rectangle และ Square ควรขยายคลาส Quadrilateral และตั้งค่าคุณสมบัติความกว้างและความสูงให้เหมาะสม โดยพื้นฐานแล้วคลาสที่ได้รับควรมีฟังก์ชันที่จำเป็นในการกำหนดค่าให้กับคุณสมบัติเหล่านี้ตามประเภทของอินสแตนซ์ Quadrilateral ที่คุณต้องคำนวณพื้นที่ โปรดสังเกตว่าทั้งคุณสมบัติความสูงและความกว้างถูกทำเครื่องหมายเป็นเสมือนในคลาสรูปสี่เหลี่ยมด้านขนานหมายความว่าคุณสมบัติเหล่านี้ควรถูกแทนที่โดยคลาสที่ได้รับคลาสรูปสี่เหลี่ยมขนมเปียกปูน
Liskov Substitution Principle เป็นส่วนเสริมของ Open Close Principle และถูกละเมิดเมื่อคุณเขียนโค้ดที่พ่น "ไม่ได้ใช้งานข้อยกเว้น" หรือคุณซ่อนเมธอดในคลาสที่ได้รับซึ่งถูกทำเครื่องหมายเป็นเสมือนในคลาสพื้นฐาน หากรหัสของคุณเป็นไปตามหลักการการทดแทน Liskov คุณจะได้รับประโยชน์มากมาย สิ่งเหล่านี้รวมถึง: การใช้งานโค้ดซ้ำ, การเชื่อมต่อที่ลดลงและการบำรุงรักษาที่ง่ายขึ้น