Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> C#

Triển khai tường minh (Explicit Implementation) của Interface trong C#

Vấn đề: Trùng tên thành viên trong nhiều Interface

Khi một class implement nhiều interface có phương thức cùng tên, cùng signature, triển khai ngầm (implicit) sẽ gộp chung một implementation cho tất cả interface.

Explicit Implementation giải quyết vấn đề này

  • Cú pháp: InterfaceName.MethodName()
  • Method không có access modifier (implicit private).
  • Chỉ có thể gọi khi cast đối tượng về interface cụ thể.
  • Cho phép implementation khác nhau cho từng interface.

Ví dụ cơ bản


interface ICar 
{
    void Display();
}

interface IBike 
{
    void Display();
}

class ShowRoom : ICar, IBike 
{
    // Explicit implementation cho ICar
    void ICar.Display() 
    {
        Console.WriteLine("Hiển thị thông tin xe hơi");
    }
    
    // Explicit implementation cho IBike
    void IBike.Display() 
    {
        Console.WriteLine("Hiển thị thông tin xe máy");
    }
}

class Program 
{
    static void Main() 
    {
        var showroom = new ShowRoom();
        
        // ❌ Không thể gọi trực tiếp: showroom.Display(); // Compile Error
        
        // ✅ Phải cast về interface
        ICar car = showroom;
        car.Display(); // Output: Hiển thị thông tin xe hơi
        
        IBike bike = showroom;
        bike.Display(); // Output: Hiển thị thông tin xe máy
        
        // Hoặc cast trực tiếp
        ((ICar)showroom).Display();
        ((IBike)showroom).Display();
    }
}

Kết hợp Implicit + Explicit


interface ILogger 
{
    void Log(string message);
}

interface IAuditable 
{
    void Log(string message);
}

class Service : ILogger, IAuditable 
{
    // Implicit implementation - dùng cho ILogger (mặc định)
    public void Log(string message) 
    {
        Console.WriteLine($"[LOG] {message}");
    }
    
    // Explicit implementation - chỉ cho IAuditable
    void IAuditable.Log(string message) 
    {
        Console.WriteLine($"[AUDIT] {DateTime.Now}: {message}");
    }
}

// Sử dụng
var service = new Service();
service.Log("User login");           // [LOG] User login (implicit)

ILogger logger = service;
logger.Log("User login");            // [LOG] User login

IAuditable audit = service;
audit.Log("User login");             // [AUDIT] 2024-01-15 10:30: User login

Khi nào dùng Explicit Implementation?

Trường hợpGiải pháp
Hai interface có method trùng tên/signatureBắt buộc explicit cho ít nhất một
Muốn ẩn method khỏi public API của classExplicit (chỉ gọi qua interface)
Implementation khác nhau cho từng interfaceExplicit cho từng interface
Implement interface cũ (legacy) nhưng không muốn lộ APIExplicit
Property/Event trùng tênExplicit implementation

Explicit Property Implementation


interface IReadOnly 
{
    string Name { get; }
}

interface IWriteOnly 
{
    string Name { set; }
}

class Entity : IReadOnly, IWriteOnly 
{
    private string _name;
    
    // Explicit get cho IReadOnly
    string IReadOnly.Name => _name;
    
    // Explicit set cho IWriteOnly
    string IWriteOnly.Name 
    {
        set => _name = value?.Trim();
    }
}

Explicit Event Implementation


interface INotifier 
{
    event EventHandler Notified;
}

class Service : INotifier 
{
    private event EventHandler _notified;
    
    event EventHandler INotifier.Notified 
    {
        add => _notified += value;
        remove => _notified -= value;
    }
    
    public void Trigger() => _notified?.Invoke(this, EventArgs.Empty);
}

Lưu ý quan trọng

  • Explicit implementation members là implicitly private - không thể dùng public, private, protected.
  • Không thể gọi trực tiếp trên instance class - phải cast.
  • Virtual/Abstract: Explicit implementation có thể virtual (trong class abstract/base) để derived class override.
  • Interface default implementation (C# 8+): Có thể cung cấp default body trong interface, class không cần implement.

Virtual Explicit Implementation


interface IPlugin 
{
    void Execute();
}

abstract class PluginBase : IPlugin 
{
    // Virtual explicit - cho derived override
    public virtual void IPlugin.Execute() 
    {
        Console.WriteLine("Base execution");
    }
}

class MyPlugin : PluginBase 
{
    // Override explicit implementation
    public override void IPlugin.Execute() 
    {
        Console.WriteLine("Custom execution");
    }
}