2010-07-15 6 views
9

Tôi cần tạo quá tải cho các chức năng trên giao diện hiện tại mà không ảnh hưởng đến bất kỳ thành phần nào hiện đang triển khai hoặc sử dụng giao diện (lý tưởng).Thêm chức năng mới vào giao diện

tôi con tôi có một vài lựa chọn:

Giản gốc giao diện:

public interface IServerComponent 
{ 
    bool Add(int a, int b); 
} 

tôi có thể thêm các chức năng quá tải mới cho giao diện và buộc mỗi lớp mà thực hiện giao diện để thực hiện các chức năng mới.

public interface IServerComponent 
{ 
    bool Add(int a, int b); 
    bool Add(int a, int b, int c); 
} 

Hoặc tôi có thể tạo giao diện mới triển khai giao diện gốc. Sau đó, các lớp khác sử dụng bản gốc sẽ không cần thay đổi và bất kỳ lớp học mới nào có thể triển khai giao diện mới ...

public interface IServerComponent2 : IServerComponent 
{ 
    bool Add(int a, int b, int c); 
} 

Thực tiễn tốt nhất là tình huống này là gì? Có bất kỳ tùy chọn nào khác không?

Cảm ơn

Trả lời

11

Nếu các phương pháp mới có thể được biểu diễn dưới dạng các phương pháp cũ, bạn có thể sử dụng phương pháp khuyến nông:

// Original interface 
public interface IServerComponent 
{ 
    bool Add(int a, int b, int c); 
} 

// New overload 
public static class MyServerMethods 
{ 
    public static bool Add(this IServerComponent component, int a, int b) 
    { 
    return component.Add(a, b, 0); 
    } 
} 

Nếu các phương pháp không thể được diễn tả như thế (ví dụ, họ thực sự cần phải được thực hiện bởi chính các thành phần), sau đó tôi khuyên bạn nên xác định giao diện mới. Cách tiếp cận này có khả năng tương thích ngược tối đa.

+0

+1 để đề cập đến các phương pháp mở rộng – ram

+1

Phương pháp mở rộng sẽ hoạt động, nhưng cũng sẽ có tác dụng lan truyền chức năng của lớp thực hiện giảm sự gắn kết. Tôi thấy điều này như một giải pháp tạm thời ở mức tốt nhất. Trong trường hợp bạn không thể mở rộng lớp, vì bạn không có quyền truy cập vào nguồn, thì các phương thức mở rộng có ý nghĩa. Tôi có thể làm theo cách này cho các cập nhật nhỏ cho một cơ sở mã hiện có, nhưng tôi chắc chắn sẽ đặt nó vào danh sách các phép tái cấu trúc cho bản phát hành chính tiếp theo. – tvanfosson

+2

Điều này hoàn toàn phụ thuộc vào thiết kế. Nếu bạn đang thêm * chức năng mới *, thì tôi đồng ý; nó thuộc về một giao diện. Nếu bạn đang thêm * quá tải * (ví dụ: chức năng gần như giống hệt nhau, luôn thể hiện được về các chức năng khác), thì tôi không đồng ý. Trong trường hợp này, các phương thức mở rộng cho phép * trực giao *, giảm trùng lặp mã. [Joe Duffy] (http://www.bluebytesoftware.com/blog/2010/02/10/ExtensionMethodsAsDefaultInterfaceMethodImplementations.aspx) có một bài đăng trên blog tốt về chủ đề này. –

4

Nếu giao diện IServerComponent của bạn chưa được giao hoặc là giao diện nội bộ chỉ được lớp của bạn triển khai và thành viên giao diện mới có ý nghĩa đối với tất cả các lớp hiện có triển khai giao diện, hãy thay đổi giao diện hiện có.

Nếu không, hãy tạo giao diện IServerComponent2 mở rộng IServerComponent. IIRC đây là những gì Hướng dẫn thiết kế khung đề xuất. Một ví dụ về điều này có thể được tìm thấy trong Khuôn khổ .NET dưới dạng lớp X509Certificate2.

Tuy nhiên, nếu các thành viên mới có thể được thực hiện trong điều khoản của các thành viên ban đầu, bạn cũng có thể sử dụng extension methods:

public interface IServerComponent 
{ 
    bool Add(int a, int b); 
} 

public static class ServerComponentExtensions 
{ 
    public static bool Add(this IServerComponent isc, int a, int b, int c) 
    { 
     return isc.Add(a, b) && isc.Add(b, c) && isc.Add(c, a); 
    } 
} 
0

Nó phụ thuộc vào bối cảnh - nếu có nhiều lớp mà thực hiện giao diện ban đầu, hoặc nếu nó được xuất bản, thì cách thực tế duy nhất là giới thiệu cái mới. Mặt khác, chỉ có một giao diện là sạch hơn trong thời gian dài, vì vậy tôi sẽ nói refactor một hiện tại nếu bạn có thể đủ khả năng đó.

0

Nếu bạn không cần hoặc muốn thay đổi các lớp học (hiện tại hoặc trong tương lai) đã triển khai giao diện cũ, bạn chỉ cần tạo giao diện thứ hai. Tuy nhiên, nó cảm thấy giống như một hack, và có thể cung cấp cho bạn mã trực quan ít hơn.

Ngoài ra, việc trì hoãn việc tái cấu trúc không bao giờ là ý tưởng hay trong trải nghiệm của tôi. Vì vậy, nếu bạn nghi ngờ bạn sẽ cần phải thực hiện các giao diện sau này, bạn cũng có thể chỉ cần thay đổi một trong những hiện có và phụ tùng cho mình một số nhức đầu. Nó chắc chắn là cách sạch hơn để làm điều đó.

0

Tôi nghĩ rằng việc duy trì một giao diện duy nhất là dễ dàng hơn nhưng cách tiếp cận thứ hai với giao diện 2 là tốt hơn bởi vì không phải tất cả các lớp học cần phải thực hiện bool Add(int a, int b, int c);

1

Tôi nhận ra ví dụ của bạn là giả tạo nhưng tôi muốn cung cấp cho bạn một câu trả lời giả tạo đó là khác với những gì bạn thể hiện để có thể bạn nghĩ về nó theo một cách khác. Thay vì có phương thức giao diện của bạn hoạt động trên một cái gì đó cụ thể nó có thể có ý nghĩa với nó thay vì làm việc trên một cái gì đó trừu tượng.

Ví dụ

public interface IAddableThings 
{ 
    int a; 
    int b; 
} 

public interface IOtherAddableThings : IAddableThings 
{ 
    int a; 
    int b; 
} 

public interface IServerComponent 
{ 
    bool Add(IAddableThings things); 
} 

Nếu đây thực sự là một Add sau đó tôi nghĩ rằng đây có ý nghĩa nhiều hơn, nhưng nếu nó thực sự giống như Calculate(), sau đó bạn sẽ muốn di chuyển một số hoặc tất cả các các phương thức đó hoạt động với các đối tượng IAddableThings.

public interface IAddableThings 
{ 
    int a; 
    int b; 
    bool CalculateMe(); 
}