Liskov Substitution Principle là nguyên tắc mà khi chúng ta extend một class, chúng ta phải đảm bảo tính đúng đắn của class đó.
Một ví dụ mà các bạn thường thấy khi tìm hiểu về nguyên tắc này đó là hình chữ nhật phải là hình chữ nhật, chiều rộng và chiều dài phải luôn luôn khác nhau:
1 2 3 4 5 6 7 8 9 10 11 |
package com.huongdankotlin.designpattern.lsp open class Rectangle { open var width: Int = 0 open var height: Int = 0 fun area(): Int { return this.width * this.height; } } |
Các bạn không nên extends class định nghĩa hình chữ nhật để xây dựng class hình vuông rồi định nghĩa 2 cạnh của hình vuông luôn bằng nhau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
package com.huongdankotlin.designpattern.lsp class Square : Rectangle() { override var width: Int get() = super.width set(value) { super.width = value super.height = value } override var height: Int get() = super.height set(value) { super.height = value super.width = value } } |
Để khi chúng ta khởi tạo 2 đối tượng Rectangle với 2 implementation khác nhau, kết quả khi tính diện tích lại khác nhau, mặc dù chúng đều là hình chữ nhật và có cùng chiều dài và chiều rộng:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
package com.huongdankotlin.designpattern.lsp fun main() { var r1 = Rectangle() r1.width = 5 r1.height = 4 println(r1.area()) var r2: Rectangle = Square() r2.width = 5 r2.height = 4 println(r2.area()) } |
Kết quả:
1 2 3 4 5 |
package com.huongdankotlin.designpattern.lsp interface Shape { fun area(): Int } |
2 class Rectangle và Square lúc này sẽ implement interface Shape:
1 2 3 4 5 6 7 8 9 10 11 |
package com.huongdankotlin.designpattern.lsp open class Rectangle: Shape { var width: Int = 0 var height: Int = 0 override fun area(): Int { return this.width * this.height; } } |
và:
1 2 3 4 5 6 7 8 9 |
package com.huongdankotlin.designpattern.lsp class Square : Shape { var side: Int = 0 override fun area(): Int { return side * side; } } |
Và khi tính diện tích của 2 hình trên:
1 2 3 4 5 6 7 8 9 10 11 12 |
package com.huongdankotlin.designpattern.lsp fun main() { var r1: Rectangle = Rectangle() r1.width = 5 r1.height = 4 println(r1.area()) var r2: Square = Square() r2.side = 5 println(r2.area()) } |
kết quả sẽ luôn đúng đắn: