Liskov Substitution Principle (LSP - Nguyên tắc Thay thế Liskov)

“Class cha có hành vi gì, thì class con phải có ĐẦY ĐỦ hành vi đó. Nghĩa là ta có thể thay thế class cha bằng class con mà hoàn toàn không phá vỡ ứng dụng.”

Điều thú vị: nguyên tắc được phát biểu lần đầu bởi bà Barbara Liskov, một nhà khoa học máy tính xuất sắc. Nghe đơn giản nhưng rất dễ vi phạm nếu không cẩn thận khi dùng kế thừa.

✅ Tốt: ghi đè trả về kiểu con của kiểu gốc

<?php
class Car {
    public function drive() { return "Lái xe"; }
}
class SuperCar extends Car {
    public function drive() { return "Lái siêu xe"; }
}
 
class CarFactory {
    public function makeNewCar(): Car { return new Car(); }
}
// Class con ghi đè: makeNewCar(): SuperCar → ỔN, vì SuperCar là lớp con của Car
// Chương trình vẫn chạy bình thường
 
function testCarFactory(CarFactory $factory) {
    $car = $factory->makeNewCar();
    echo $car->drive() . "\n";   // không lỗi
}

❌ Xấu: ghi đè trả về kiểu KHÔNG tương thích

<?php
class Ship {
    public function sail() { return "Đi thuyền"; }
}
 
// Lớp con trả về Ship (KHÔNG phải lớp con của Car)
class ShipFactory extends CarFactory {
    public function makeNewCar(): Ship { return new Ship(); }
}
 
function testCarFactory(CarFactory $factory) {
    $car = $factory->makeNewCar();
    echo $car->drive() . "\n"; // LỖI! Ship không có phương thức drive
}

Ví dụ này “lỗi” rõ ràng (IDE có thể warning sớm). Trong thực tế, vi phạm có thể được ẩn giấu khéo léo đến mức bạn không để ý - và lỗi nghiêm trọng hơn rất nhiều.

Giá trị

Đảm bảo LSP giúp code tái sử dụng an toàn, không làm thay đổi hành vi của đối tượng một cách bất ngờ → giảm thiểu tối đa lỗi.

Liên quan