Tránh triển khai mặc định trong giao diện C#

lập trình


Tôi đang tìm cách tích hợp chức năng bổ sung vào các lớp khác nhau trong C#. Tập trung vào việc triển khai mặc định cho các phương thức giao diện là một ý tưởng hay.

Hãy xem xét cấu trúc lớp sau:

Lớp A là cơ sở cho các lớp B, C và D.
Lớp E là cơ sở cho các lớp F, G và H.
Lớp O là cơ sở cho các lớp P, Q và R.

Trong số này, các lớp B, F và P phải triển khai giao diện IDoablebao gồm một phương thức X điều đó phải nhất quán trên tất cả các lớp triển khai.

Đây là một ví dụ đơn giản:

C#
public class A
{ }

public class B : A, IDoable
{ }

public class C : A
{ }

public class D : A
{ }

public class E
{ }

public class F : E, IDoable
{ }

public class G : E
{ }

public class H : E
{ }

public class O
{ }

public class P : O, IDoable
{ }

public class Q : O
{ }

public class R : O
{ }

public interface IDoable
{
    // Yuck, that smells. Default implementation.
    string X() => "I want to implement method X only once";
}

public class Test
{
    public void Run()
    {
        string bx = new B().X();
        string fx = new F().X();
        string px = new P().X();
        
        string result = bx == fx && bx == px ? "Same :)" : "Various :("; 
    }
}

Tuy nhiên, có một cuộc tranh luận về việc có nên sử dụng các cài đặt mặc định cho các phương thức giao diện trong C# hay không. Có cách tiếp cận nào khác để đạt được chức năng này mà không cần dựa vào việc triển khai mặc định không? Hoặc việc sử dụng triển khai mặc định có được chấp nhận trong trường hợp này không?

Lưu ý: A, E và O không có đặc điểm chung và không liên quan với nhau.

Những gì tôi đã thử:

Thứ nhất, tôi hạn chế triển khai X trực tiếp vào các lớp B, F và P để tránh vi phạm quy định. KHÔ nguyên tắc. Cho rằng X có nghĩa là giống hệt nhau giữa các lớp này, cách tiếp cận này có vẻ không thực tế, đặc biệt nếu X dài.

Thứ hai, tôi đã tạo một phương thức mở rộng hoạt động tốt để cung cấp chức năng X:

C#
public static class DoableExtensions
{
    public static string X(this IDoable doable)
    {
        return "I want to implement method X only once";
    }
}

Tuy nhiên, cách tiếp cận này dẫn đến một khoảng trống IDoable giao diện vi phạm “CA1040: Tránh các giao diện trống” luật lệ.

Cuối cùng, tôi đã xem xét mẫu trang trí, nhưng tôi không chắc chắn về cách triển khai nó một cách hiệu quả trong khi vẫn duy trì việc tuân thủ nguyên tắc DRY. Nhưng có thể cách tiếp cận này là giải pháp then chốt.

Giải pháp 1

Giữ câu hỏi mang tính lý thuyết khiến cho việc đưa ra câu trả lời cụ thể nếu không nắm rõ tình hình sẽ rất khó khăn. Điều này có vẻ giống như giáo viên của bạn hoặc người phỏng vấn xin việc đang cố gắng đưa ra cho bạn một câu hỏi mà không có câu trả lời đúng để xem bạn sẽ trả lời như thế nào.

Nhìn vào các tùy chọn được trình bày, giải pháp mẫu trang trí gợi ý rằng cả 3 lớp cơ sở đều có một lớp cơ sở hoặc giao diện chung. Vì vậy, giao diện trống với phương thức mở rộng sẽ là giải pháp khả thi. Lý do: bạn không thể kế thừa nhiều hơn một lớp cụ thể (cơ sở/trừu tượng) nhưng bạn có thể triển khai nhiều giao diện (ngầm/rõ ràng).

コメント

タイトルとURLをコピーしました