Interface trong C#
Nguyễn Dương 07-06-20241. INTERFACE LÀ GÌ?
Các bạn đã biết, C# không hỗ trợ đa kế thừa, 1 lớp kế thừa từ nhiều lớp. Tại sao lại như vậy, ta xét thử 2 trường hợp kế thừa dưới đây.
Giả sử ta có 4 lớp A, B, C, D.
Trường hợp 1: Lớp B kế thừa từ lớp A, lớp C kế thừa từ lớp B, lớp D kế thừa từ lớp C nhưng lớp A lại kế thừa từ lớp D.
Trường hợp 2: Lớp B và D kế thừa từ lớp A, lớp C kế thừa từ lớp D, lớp B kế thừa từ lớp C.
Bạn thử nghĩ xem trong 2 trường hợp này thì luồng đi dữ liệu kiểu gì, thừa hưởng thuộc tính và phương thức kiểu gì, xử lý ra sao.
Về lý thuyết thì ngôn ngữ lập trình không cần hạn chế điều này, tất cả do lập trình viên nhưng quan điểm của Microsoft thì họ muốn lập trình với C# phải tường minh, hạn chế lỗi.
Nhưng nếu không hỗ trợ đa kế thừa thì có bị hạn chế gì không, đa kế thừa giúp ích gì. Ta xét thử ví dụ sau.
Giả sử mình có 2 lớp
- Động vật trên cạn
- Động vật dưới nước
Tiếp theo mình tạo 1 lớp Ếch. Vì ếch là loài lưỡng cư nên nó phải được thừa hưởng thuộc tính và phương thức của cả 2 lớp Động vật trên cạn và Động vật dưới nước. Nhưng C# không hỗ trợ đa kế thừa, vì vậy Interface ra đời như một giải pháp thay thế.
Interface được hiểu như là 1 khuôn mẫu chung mà mọi lớp thực thi nó đều phải tuân theo. Bên trong Interface là 1 tập hợp các thành phần chỉ có khai báo mà không có phần định nghĩa.
Các thành phần đó bao gồm:
- Phương thức
- Property
- Event
- Indexers
Đặc điểm của Interface
- Chỉ chứa khai báo không chứa phần định nghĩa.
- Việc ghi đè 1 thành phần trong interface cũng không cần từ khoá override.
- Không thể khai báo phạm vi truy cập cho các thành phần bên trong interface. Các thành phần này sẽ mặc định là public.
- Interface không chứa các thuộc tính (các biến) dù là hằng số hay biến tĩnh vẫn không được.
- Interface không có hàm khởi tạo và hàm hủy.
- Các lớp có thể thực thi nhiều interface cùng lúc, đây là giải pháp thay thế đa kế thừa.
- Một interface có thể kế thừa nhiều interface khác nhưng không thể kế thừa bất kỳ lớp nào.
Bạn thử nghĩ xem trong 2 trường hợp này thì luồng đi dữ liệu kiểu gì, thừa hưởng thuộc tính và phương thức kiểu gì, xử lý ra sao.
Về lý thuyết thì ngôn ngữ lập trình không cần hạn chế điều này, tất cả do lập trình viên nhưng quan điểm của Microsoft thì họ muốn lập trình với C# phải tường minh, hạn chế lỗi.
Nhưng nếu không hỗ trợ đa kế thừa thì có bị hạn chế gì không, đa kế thừa giúp ích gì. Ta xét thử ví dụ sau.
Giả sử mình có 2 lớp
- Động vật trên cạn
- Động vật dưới nước
Tiếp theo mình tạo 1 lớp Ếch. Vì ếch là loài lưỡng cư nên nó phải được thừa hưởng thuộc tính và phương thức của cả 2 lớp Động vật trên cạn và Động vật dưới nước. Nhưng C# không hỗ trợ đa kế thừa, vì vậy Interface ra đời như một giải pháp thay thế.
Interface được hiểu như là 1 khuôn mẫu chung mà mọi lớp thực thi nó đều phải tuân theo. Bên trong Interface là 1 tập hợp các thành phần chỉ có khai báo mà không có phần định nghĩa.
Các thành phần đó bao gồm:
- Phương thức
- Property
- Event
- Indexers
Đặc điểm của Interface
- Chỉ chứa khai báo không chứa phần định nghĩa.
- Việc ghi đè 1 thành phần trong interface cũng không cần từ khoá override.
- Không thể khai báo phạm vi truy cập cho các thành phần bên trong interface. Các thành phần này sẽ mặc định là public.
- Interface không chứa các thuộc tính (các biến) dù là hằng số hay biến tĩnh vẫn không được.
- Interface không có hàm khởi tạo và hàm hủy.
- Các lớp có thể thực thi nhiều interface cùng lúc, đây là giải pháp thay thế đa kế thừa.
- Một interface có thể kế thừa nhiều interface khác nhưng không thể kế thừa bất kỳ lớp nào.
2. KHAI BÁO VÀ SỬ DỤNG INTERFACE
Khai báo:
Lưu ý: Để dễ phân biệt, các lập trình viên thường thêm chữ "I" vào đằng trước tên interface. Ví dụ IShape, IAnimal ......
Sử dụng:
Ví dụ: Lớp ếch kế thừa 2 interface là động vật trên cạn và động vật dưới nước.
Kết quả
Vì việc thực thi interface rất giống với kế thừa nên ta hoàn toàn có thể sử dụng câu lệnh sau:
Kết quả chỉ in ra màn 1 dòng chữ: Ech nhay cao 20 cm. Vì lệnh trên là tạo E1 thừa hưởng interface động vật trên cạn nên chỉ gọi được hàm Jump.
- Loại bỏ public khỏi hàm Move
- Sử dụng từ khóa as để chỉ rõ đang gọi hàm Move của interface nào
Ví dụ:
Kết quả vẫn ra như lúc đầu.
- Đều có thể chứa phương thức trừu tượng
- Đều không thể khởi tạo đối tượng
Khác nhau:
Qua bài này, chúng ta nắm được các kiến thức cơ bản để lập trình với C#. Các bạn hãy ôn tập thật kỹ để sang bài sau, chúng ta sẽ áp dụng tất cả các kiến thức này để lập trình một số phần mềm đơn giản trên Windows nhé.
interface <tên interface> { // Các thành phần bên trong }
Lưu ý: Để dễ phân biệt, các lập trình viên thường thêm chữ "I" vào đằng trước tên interface. Ví dụ IShape, IAnimal ......
Sử dụng:
Ví dụ: Lớp ếch kế thừa 2 interface là động vật trên cạn và động vật dưới nước.
namespace Vi_du
{
interface IDongVatTrenCan
{
void Jump();
}
interface IDongVatDuoiNuoc
{
void Swim();
}
class Ech : IDongVatTrenCan, IDongVatDuoiNuoc
{
public void Jump()
{
Console.WriteLine("Ech nhay cao 20 cm");
}
public void Swim()
{
Console.WriteLine("Ech boi rat xa");
}
}
class Program
{
static void Main(string[] args)
{
Ech E1 = new Ech();
E1.Jump();
E1.Swim();
Console.ReadLine();
}
}
}
Kết quả
Vì việc thực thi interface rất giống với kế thừa nên ta hoàn toàn có thể sử dụng câu lệnh sau:
IDongVatTrenCan E1 = new Ech();
E1.Jump();
3. XỬ LÝ KHI TRÙNG TÊN HÀM
Xét ví dụ trên, giả sử 2 hàm trong 2 interface động vật trên cạn và động vật dưới nước, mình không đặt tên là Jump và Swim nữa, mà đặt tên chung là Move. Vậy làm sao để chương trình biết là đang gọi hàm Move của interface nào.
Để giải quyết trường hợp này, ta làm như sau: - Loại bỏ public khỏi hàm Move
- Sử dụng từ khóa as để chỉ rõ đang gọi hàm Move của interface nào
Ví dụ:
namespace Vi_du
{
interface ILandAnimal
{
void Move();
}
interface IWaterAnimal
{
void Move();
}
class Frog : ILandAnimal, IWaterAnimal
{
void ILandAnimal.Move()
{
Console.WriteLine("Ech nhay cao 20 cm");
}
void IWaterAnimal.Move()
{
Console.WriteLine("Ech boi rat xa");
}
}
class Program
{
static void Main(string[] args)
{
Frog E1 = new Frog();
(E1 as ILandAnimal).Move();
(E1 as IWaterAnimal).Move();
Console.ReadLine();
}
}
}
Kết quả vẫn ra như lúc đầu.
4. SO SÁNH INTERFACE VÀ ABSTRACT
Giống nhau:- Đều có thể chứa phương thức trừu tượng
- Đều không thể khởi tạo đối tượng
Khác nhau:
interface | abstract class |
Chỉ có thể kế thừa từ interface khác | Có thể kế thừa từ 1 lớp hoặc nhiều interface |
Chỉ chứa khai báo, không có nội dung | Có thể chứa các thuộc tính và phương thức như class bình thường |
Không sử dụng override để ghi đè | Sử dụng override để ghi đè |
Không có hàm khởi tạo và hàm hủy | Có hàm khởi tạo và hàm hủy |
Không thể khai báo phạm vi truy cập, mặc định là public | Có thể khai báo phạm vi truy cập |
Dùng để định nghĩa 1 khuôn mẫu chung | Định nghĩa thành phần chung của lớp, sử dụng chung cho nhiều đối tượng cùng kiểu |
Tốn thời gian để tìm phương thức tương ứng với lớp nên xử lý chậm hơn | Nhanh hơn so với interface |
Bài viết liên quan
Interface trong C#
Tính đa hình trong C#
Tính kế thừa trong C#
this và static trong C#
Các loại phạm vi truy cập trong C#
Hàm khởi tạo và hàm hủy