- vừa được xem lúc

Hiểu Liskov Substitution Principle qua ví dụ !

0 0 24

Người đăng: Henryk Sienkiewicz

Theo Viblo Asia

Liskov Substitution Principle là gì ?

  • The principle defines that objects of a superclass shall be replaceable with objects of its subclasses without breaking the application.
  • Nguyên tắc đóng mở xác đinh rằng các instance của lớp con có thể thay thế được instance lớp cha mà vẫn đảm bảo tính đúng đắn của chương trình.

Lấy ví dụ thực tế ?

Chúng ta cần tính tổng các số nguyên trong một mảng. "Hiện đại" hơn một chút chúng ta cần tính tổng của các số chẵn trong màng này chẳng hạn ?. Hmmm !. Khởi tạo project thôi !

Trước hết là khởi tạo 2 class. Class SumCalculator

  • Method Calculate() để tính tổng các số trong mảng. Class EvenNumbersSumCalculator kế thừa class SumCalculator
  • Method Calculate() để tính tổng các số chẵn trong mảng (note : Từ khóa new được sử dụng ở đây để chỉ ra rằng người lập trình đang tạo ra một phiên bản mới cho phương thức này bên trong lớp con).
public class SumCalculator
{ protected readonly int[] _numbers; public SumCalculator(int[] numbers) { _numbers = numbers; } public int Calculate() => _numbers.Sum();
} public class EvenNumbersSumCalculator: SumCalculator
{ public EvenNumbersSumCalculator(int[] numbers) :base(numbers) { } public new int Calculate() => _numbers.Where(x => x % 2 == 0).Sum();
}
  • Bây giờ thì test 2 hàm này thôi :
class Program
{ static void Main(string[] args) { var numbers = new int[] { 5, 7, 9, 8, 1, 6, 4 }; SumCalculator sum = new SumCalculator(numbers); Console.WriteLine($"The sum of all the numbers: {sum.Calculate()}"); Console.WriteLine(); EvenNumbersSumCalculator evenSum = new EvenNumbersSumCalculator(numbers); Console.WriteLine($"The sum of all the even numbers: {evenSum.Calculate()}"); }
}
  • Kết quả của chương trình sẽ là :
The sum of all the numbers: 40 The sum of all the even numbers: 18
  • Ơ thế này là ổn rồi còn gì =)). Nhưng chúng ta biết rằng một object thuộc kiểu con có thể gán cho biến thuộc kiểu cha, tức là kiểu cơ sở có thể dùng để thay thế cho kiểu dẫn xuất (tìm hiểu tính đa hình). Trong ví dụ này thì chúng ta có thể lưu EvenNumbersSumCalculator dưới dạng biến SumCalculator
SumCalculator evenSum = new EvenNumbersSumCalculator(numbers);
Console.WriteLine($"The sum of all the even numbers: {evenSum.Calculate()}");
  • Bây giờ 2 class ban đầu sẽ sửa một chút
public class SumCalculator
{ protected readonly int[] _numbers; public SumCalculator(int[] numbers) { _numbers = numbers; } public virtual int Calculate() => _numbers.Sum();
} public class EvenNumbersSumCalculator: SumCalculator
{ public EvenNumbersSumCalculator(int[] numbers) :base(numbers) { } public override int Calculate() => _numbers.Where(x => x % 2 == 0).Sum();
}
  • Test thử lại hàm tính tổng số chẵn xem sao ?
class Program
{ static void Main(string[] args) { var numbers = new int[] { 5, 7, 9, 8, 1, 6, 4 }; SumCalculator sum = new SumCalculator(numbers); Console.WriteLine($"The sum of all the numbers: {sum.Calculate()}"); Console.WriteLine(); SumCalculator evenSum = new EvenNumbersSumCalculator(numbers); Console.WriteLine($"The sum of all the even numbers: {evenSum.Calculate()}"); }
}
  • Kết quả của chương trình sẽ là :
The sum of all the numbers: 40 The sum of all the even numbers: 40
  • Như chúng ta có thể thấy, chúng ta không nhận được kết quả như mong đợi vì biến evenSum của chúng ta thuộc loại SumCalculator, là một lớp bậc cao hơn (lớp cơ sở). Điều này có nghĩa là phương thức Sum từ SumCalculator sẽ được thực thi. Vì vậy, điều này rõ ràng là không đúng, bởi vì lớp con của chúng ta không hoạt động như một lớp thay thế cho lớp cha(không đúng với Liskov Substitution Principle) .

Bây giờ là lúc áp dụng Liskov Substitution Principle

  • Lúc này 2 class ban đầu sẽ trở thành.
// lớp cơ sở
public abstract class Calculator
{ protected readonly int[] _numbers; public Calculator(int[] numbers) { _numbers = numbers; } public abstract int Calculate();
} // lớp con tính tổng
public class SumCalculator : Calculator
{ public SumCalculator(int[] numbers) :base(numbers) { } public override int Calculate() => _numbers.Sum();
} // lớp con tính tổng số chẵn
public class EvenNumbersSumCalculator: Calculator
{ public EvenNumbersSumCalculator(int[] numbers) :base(numbers) { } public override int Calculate() => _numbers.Where(x => x % 2 == 0).Sum();
}
  • Hàm main
 class Program
{ static void Main(string[] args) { var numbers = new int[] { 5, 7, 9, 8, 1, 6, 4 }; Calculator sum = new SumCalculator(numbers); Console.WriteLine($"The sum of all the numbers: {sum.Calculate()}"); Console.WriteLine(); Calculator evenSum = new EvenNumbersSumCalculator(numbers); Console.WriteLine($"The sum of all the even numbers: {evenSum.Calculate()}"); }
}
  • Kết quả chương trình
  • Kết quả của chương trình sẽ là :
The sum of all the numbers: 40 The sum of all the even numbers: 18
  • Uầyyy. Chúng ta sẽ có kết quả tương tự** 40 & 18. Nhưng quan trọng là chúng ta có thể lưu trữ bất kỳ tham chiếu lớp con nào vào một biến lớp cơ sở và hành vi sẽ không thay đổi, đó là mục tiêu của Liskov Substitution Principle ?

Bình luận

Bài viết tương tự

- vừa được xem lúc

Các loại tham chiếu Nullable trong C# (Phần 1)

1. Giới thiệu. C# 8.0 giới thiệu kiểu tham chiếu nullable và kiểu tham chiếu non-nullable cho phép bạn đưa ra các lựa chọn quan trọng về thuộc tính cho các biến kiểu tham chiếu:.

0 0 36

- vừa được xem lúc

Command pattern qua ví dụ !

Command pattern là gì . Command pattern khá phổ biến trong C #, đặc biệt khi chúng ta muốn trì hoãn hoặc xếp hàng đợi việc thực hiện một yêu cầu hoặc khi chúng ta muốn theo dõi các hoạt động. Hơn nữa, chúng ta có thể hoàn tác tác chúng. .

0 0 178

- vừa được xem lúc

Creating custom Controls Wpf

Introduction. Wpf/winforms provides various controls like Buttons, Textbox, TextBlock, Labels etc.

0 0 41

- vừa được xem lúc

[P1] Chọn công nghệ nào để xây dựng website?

Hiện nay nhu cầu phát triển website, app tăng rất cao do xu hướng "số hóa 4.0" trong và ngoài nước.

0 0 71

- vừa được xem lúc

Kiểu dữ liệu trong C#

Dẫn nhập. Ở bài BIẾN TRONG C# chúng ta đã tìm hiểu về biến và có một thành phần không thể thiếu khi khai báo biến – Đó là kiểu dữ liệu.

0 0 24

- vừa được xem lúc

So sánh từ khóa Var và Dynamic trong C#

1. Giới thiệu về Static typing và Dynamic typing.

0 0 29