Liskov Substitution principle – Nguyên lí thay thế Liskow

Liskov Substitution principle là gì

Tiếp tục đến với phần 3 của serries nguyên lí SOLID. Mình xin nhắc lại khái niệm về nguyên lí này: objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program. Các đối tượng trong một chương trình có thể được thay thế bởi các class con mà không làm thay đổi tính đúng đắn của chương trình. Thoạt đầu mới đọc mình cũng thấy thực sự rất trìu tượng và khó hiểu. Lướt qua stackoverflow thì mình cũng tìm thấy một vài lời giải thích hay nên mình cũng đem nó vào bài viết luôn.

Ví dụ bạn có 2 class như hình dưới.

public class Broad {
    ...
}

public class ThreeDBroad extends Broad {
    ...
}

Trong class Broad lấy tọa độ X với Y để chỉ ra vị trí trong không gian 2 chiều. Nó cho phép những nhà phát triển game quản lí vị trí trong không gian 2 chiều trong suốt trò chơi. Nhưng yêu cầu được thay đổi, trò chơi ngày một nâng cấp từ phiên bản 2D quen thuộc lên phiên bản 3D, nhân vật trong game có thể bay lên chứ không chỉ di chuyển bình thường nữa. Do vậy cần thêm class ThreeDBroad extends Broad.

Thoạt nhìn có vẻ khá ổn. Class Broad đã cung cấp height width và class ThreeDBroad ZPos, như vậy đã đủ để tạo nên không gian 3 chiềuiều, các hàm tính toán cũng đã được làm sẵn trong Broad. Nhưng đó mới chính là vấn đề cần giải quyết và nó cũng vi phạm nguyên lí này.

Các phương thức trong class Broad chỉ yêu cầu 2 tham số là xy nhưng ở class ThreeDBroad cần 3 tham số là x, yz để biểu diễn đủ 3 tọa độ. Và sau đó bạn phải thực hiện lại các phương thức mới tham số z. Các phương thức được kế thừa từ Broad sẽ mất đi ý nghĩa của nó.

Một ví dụ khác, bạn hãy nhìn lại hình ảnh 2 con vịt, trong đó có một con vịt chạy pin và một con vịt thịt được.

public class Duck {
    public void eat() {
        ...
    }
    public boolean canBeEaten() {
    
    }
}

public class DuckToy extends Duck {
    ...
}

Vịt thịt được có thể ăn và có thể “bị” thịt, còn vịt đồ chơi thì không ăn được và cũng không “bị” thịt được. Như vậy class DuckToy không thể thay thế class cha là Duck được. Vi phạm rõ ràng Liskov Substitution principle.

Thực ra bản chất của nguyên lí này giúp chúng ta có một định hướng tốt hơn khi sử dụng và thừa kế các  class, tránh gặp các lỗi khó nhai. Vì nó trìu tượng nên dễ bị vi phạm, do đó mỗi khi thiết kế cần được xem xét kỹ lưỡng.

Series Navigation<< Open/Closed Principle – Nguyên lí đóng mở thế giớiInterface Segregation Principle – Nguyên lí phân biệt interface >>

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *