Tính kế thừa (Inheritance) là một trong bốn trụ cột quan trọng của lập trình hướng đối tượng (OOP).
Nếu chưa hiểu rõ về lập trình hướng đối tượng thì bạn nên tham khảo bài viết dưới đây trước:
Tính kế thừa là khả năng tạo một lớp mới dựa trên một lớp có sẵn. Lớp có sẵn là lớp cha, lớp mới là lớp con và lớp con thừa kế các thành phần được định nghĩa ở lớp cha.
Hãy xem ví dụ về hệ thống phân cấp lớp sau đây:
public class Small
{
}
public class Big: Small
{
}
public class Bigger : Big
{
}
Theo ví dụ trên, Small
là lớp cơ sở cho lớp Big
và lớp Big
là lớp cơ sở cho lớp Bigger
. Điểm cần nhớ ở đây là một lớp dẫn xuất sẽ luôn có một cái gì đó nhiều hơn một lớp cơ sở, vì vậy lớp cơ sở tương đối nhỏ hơn lớp dẫn xuất.
Bây giờ, hãy xem xét việc khởi tạo sau:
Như bạn có thể thấy ở trên, một lớp cơ sở có thể chứa một lớp dẫn xuất nhưng một lớp dẫn xuất không thể chứa một lớp cơ sở.
Nói cách khác, có thể tạo thể hiện của lớp con và gán cho một biến của lớp cha nhưng không thể tạo thể hiện của lớp cha và gán cho một biến của lớp con.
Bây giờ, chúng ta hãy tìm hiểu về hiệp phương sai và chống chỉ định trong C#.
Hiệp phương sai (Covariance) cho phép bạn truyền một kiểu dẫn xuất cho một phương thức yêu cầu một kiểu cơ sở.
Về cơ bản, lớp dẫn xuất là lớp cơ sở được bổ sung thêm các chức năng. Vì vậy, hiệp phương sai cho phép bạn sử dụng một lớp dẫn xuất để thay cho một lớp cơ sở.
Hiệp phương sai có thể được áp dụng trên delegate
, generic
, array
, interface
, v.v.
Small small1 = new Big();
Small small2 = new Bigger();
Big big = new Bigger();
object[] objs = new string[10];
Nếu bạn chưa đọc bài hướng dẫn về delegate
thì có thể tham khảo tại đây trước khi tiếp tục nhé:
Hiệp phương sai với delegate
cho phép linh hoạt trong kiểu trả về của các phương thức delegate
. Hãy xem ví dụ sau:
public delegate Small CovarDel(Big mc);
class Program
{
static Big Method1(Big bg)
{
Console.WriteLine("Method1");
return new Big();
}
static Small Method2(Big bg)
{
Console.WriteLine("Method2");
return new Small();
}
static void Main(string[] args)
{
CovarDel del = Method1;
Small sm1 = del(new Big());
del = Method2;
Small sm1 = del(new Big());
}
}
Kết quả khi biên dịch và thực thi chương trình như sau:
Method1
Method2
Như bạn có thể thấy trong ví dụ trên, delegate
mong đợi một kiểu trả về là Small
(lớp cơ sở) nhưng chúng ta vẫn có thể gán Method1
trả về kiểu Big
(lớp dẫn xuất) và Method2
có chữ ký giống như mong đợi của delegate
.
Do đó, hiệp phương sai cho phép bạn gán một phương thức cho delegate
có kiểu trả về ít dẫn xuất hơn.
Chống chỉ định (Contravariance) được áp dụng cho các tham số. Chống chỉ định cho phép một phương thức với tham số của lớp cơ sở được gán cho một delegate
yêu cầu tham số của lớp dẫn xuất.
Tiếp tục với ví dụ trên, thêm phương thức Method3
có kiểu tham số khác với delegate
như sau:
delegate Small CovarDel(Big mc);
class Program
{
static Big Method1(Big bg)
{
Console.WriteLine("Method1");
return new Big();
}
static Small Method2(Big bg)
{
Console.WriteLine("Method2");
return new Small();
}
static Small Method3(Small sml)
{
Console.WriteLine("Method3");
return new Small();
}
static void Main(string[] args)
{
CovarDel del = Method1;
del += Method2;
del += Method3;
Small sm = del(new Big());
}
}
Kết quả khi biên dịch và chạy chương trình:
Method1
Method2
Method3
Như bạn có thể thấy, Method3
có một tham số của lớp Small
trong khi delegate
yêu cầu một tham số của lớp Big
. Tuy nhiên, bạn có thể sử dụng Method3
với delegate
.
Bạn cũng có thể sử dụng hiệp phương sai và chống chỉ định trong cùng một phương thức như dưới đây.
delegate Small CovarDel(Big mc);
class Program
{
static Big Method4(Small sml)
{
Console.WriteLine("Method4");
return new Big();
}
static void Main(string[] args)
{
CovarDel del = Method4;
Small sm = del(new Big());
}
}
Kết quả khi biên dịch và chạy chương trình:
Method4
Có bạn nào bị nhức đầu, chóng mặt khi đọc tới đây không? Hãy để lại comment bên dưới cho mọi người biết nhé.
Bạn có thể vui lòng tắt trình chặn quảng cáo ❤️ để hỗ trợ chúng tôi duy trì hoạt động của trang web.
Trong loạt bài này, tôi sẽ xem xét một số
Ngôn ngữ C# đã bật các bộ tăng áp liên
Trong bài viết này, chúng ta sẽ tìm hiểu lớp tiện ích ZipFile trong C#, cách nén tập tin và thư mục, cùng với giải nén tập tin zip.
Bài viết này sẽ giới thiệu cách đơn giản nhất mà tôi đã tìm thấy để đọc và ghi file Excel bằng C# sử dụng ExcelMapper.