VieTopik
Tiếng HànTiếng AnhIT
  • Góc học tập
Tải app
  • Thư viện
  • Luyện thi
  • Cẩm nang
  • Góc học tập
OOP và thiết kếInterface và composition
Bài 5/12
5 phút

Interface

Nội dung bài · 5 mục
  1. 1.Khái niệm
  2. 2.Ví dụ
  3. 3.Thử ngay
  4. 4.Lỗi hay gặp
  5. 5.Tóm tắt

Đặt hàng xong, hệ thống gửi email cho khách. Tháng sau sếp muốn gửi thêm SMS. Nếu code đặt hàng gắn chặt với email thì phải sửa chính code đó. Interface giúp code đặt hàng chỉ cần biết "có ai đó gửi được thông báo", còn gửi bằng gì thì tuỳ.

Khái niệm

📜 Interface: danh sách method và property mà một class phải có, thường không kèm cách làm.

🤝 Implement: class ghi : TênInterface thì cam kết viết đủ mọi thành viên của interface đó, thiếu một cái là lỗi compile.

Ví dụ

var order = new PlaceOrder(new EmailNotifier());
order.Run();

interface INotifier
{
    void Send(string message);
}

class EmailNotifier : INotifier
{
    public void Send(string message) =>
        Console.WriteLine($"Email: {message}");
}

class PlaceOrder
{
    private readonly INotifier _notifier;

    public PlaceOrder(INotifier notifier)
    {
        _notifier = notifier;
    }

    public void Run() => _notifier.Send("Đã đặt hàng");
}
  • interface INotifier chỉ khai báo Send, không có thân. Tên interface bắt đầu bằng chữ I.
  • EmailNotifier : INotifier implement interface, nên phải có method Send và để public.
  • PlaceOrder chỉ biết INotifier, không biết email. Nó nhận notifier qua constructor.
  • readonly nghĩa là field chỉ gán được lúc khai báo hoặc trong constructor, sau đó không đổi (giống property { get; } ở bài Property và constructor). Field private theo quy ước .NET bắt đầu bằng _.
  • Không new INotifier() được, nhưng biến kiểu INotifier thì giữ được bất kỳ class nào implement nó.
  • Một class implement được nhiều interface: class Shop : INotifier, IPrinter.

Thử ngay

Chép ví dụ trên vào Program.cs. Thêm class dưới đây vào cuối file, rồi thay hai dòng đầu bằng đoạn gọi mới:

class SmsNotifier : INotifier
{
    public void Send(string message) =>
        Console.WriteLine($"SMS: {message}");
}
new PlaceOrder(new EmailNotifier()).Run();
new PlaceOrder(new SmsNotifier()).Run();

Đoán trước khi chạy: dòng thứ hai in ra gì?

Xem kết quả
Email: Đã đặt hàng
SMS: Đã đặt hàng

Dòng thứ hai là SMS: Đã đặt hàng. PlaceOrder gọi Send của object được truyền vào. Thêm cách gửi mới chỉ cần viết class mới, không sửa PlaceOrder.

Lỗi hay gặp

Implement thiếu thành viên. Class đã ghi : INotifier thì phải viết đủ.

// SAI — lỗi compile: thiếu method Send
class PushNotifier : INotifier
{
}
// ĐÚNG
class PushNotifier : INotifier
{
    public void Send(string message) =>
        Console.WriteLine($"Push: {message}");
}

Tạo object từ interface. Interface không có code để chạy.

// SAI — lỗi compile: không new được interface
INotifier notifier = new INotifier();
// ĐÚNG — new một class implement interface đó
INotifier notifier = new EmailNotifier();

Tóm tắt

  • Interface liệt kê method và property mà class phải có, không kèm cách làm.
  • Class : TênInterface phải implement đủ mọi thành viên, để public.
  • Code chỉ phụ thuộc vào interface thì đổi được cách làm mà không phải sửa code đó.
  • Không new được interface. Một class implement được nhiều interface.
  • Từ C# 8, method trong interface có thể kèm thân sẵn (default method), class không bắt buộc viết lại method đó.

Tự kiểm tra

0/3 câu
Câu 1

interface IPrinter { void Print(string text); } Class nào implement IPrinter đúng?

Câu 2

Class ReportService nhận IExporter qua constructor. Muốn xuất thêm định dạng Excel, cần làm gì?

Câu 3

Dòng nào KHÔNG biên dịch được, biết EmailNotifier implement INotifier?

Abstract classInterface hay abstract class

Nội dung bài

  1. 1.Khái niệm
  2. 2.Ví dụ
  3. 3.Thử ngay
  4. 4.Lỗi hay gặp
  5. 5.Tóm tắt