2011-08-30 44 views
18

Tôi có một lớp học kế thừa giao diện. Một phương thức thành viên giao diện được thực hiện trong lớp của tôi mà không có một công cụ sửa đổi truy cập (do đó, theo mặc định nó là riêng tư).Tại sao phương thức giao diện C# được triển khai trong một lớp là công khai?

Tôi gặp lỗi "không thể triển khai thành viên giao diện vì nó không công khai".

Tại sao không được phép? Tôi không thể ghi đè khả năng truy cập?

Trả lời

29

Dưới đây là một ví dụ về tại sao nó không có ý nghĩa để có thể ghi đè lên visibility:

interface someI 
{ 
    void doYourWork(); 
} 
public class A : someI 
{ 
    public void doYourWork() 
    { 
     //... 
    } 
} 

public class B : someI 
{ 
    private void doYourWork() 
    { 
     //... 
    } 
} 
void Main() 
{ 
    List<someI> workers = getWorkers(); 
    foreach(var worker in workers) 
     worker.doYourWork(); 
} 

gì xảy ra khi nhân viên của bạn là loại B? Bạn đang gọi một phương thức như thể nó là công khai, nhưng đó là một phương pháp riêng tư. Nếu bạn muốn chức năng này, thì nó không thực sự là một phương pháp riêng tư phải không?

Nếu bạn chỉ muốn nó được công khai khi tham chiếu thông qua giao diện của bạn, sau đó bạn có thể định nghĩa nó như vậy:

public class B : someI 
{ 
    void someI.doYourWork() 
    { 
     //... 
    } 
} 

Và bạn kết thúc với điều này:

var b = new B(); 
b.doYourWork(); // Not accessible 
((someI)b).doYourWork(); // Accessible 
+3

Tôi sẽ đề nghị rằng đối với các lớp chưa được niêm yết, các giao diện có triển khai sẽ không hiển thị các thành viên lớp công khai có cùng tên và chữ ký cần được triển khai bằng các thành viên ảo được bảo vệ; Thật không may, một trong những gần nhất có thể đến để làm điều đó trong C# là có một giao diện thực hiện đơn giản chỉ cần gọi một phương pháp ảo được bảo vệ. Nếu không, nếu một lớp dẫn xuất thực hiện lại một giao diện sẽ không có cách nào để gọi thực hiện cha mẹ. – supercat

+1

@supercat Có lẽ chỉ là sớm, nhưng tôi không chắc là tôi đang theo dõi bạn; những gì bạn có nghĩa là bởi 'Nếu không, nếu một lớp dẫn xuất lại thực hiện một giao diện sẽ không có cách nào để gọi thực hiện phụ huynh'? Tại sao bạn muốn có một phương thức được bảo vệ thực hiện một giao diện (bạn sẽ không thể truy cập nó thông qua giao diện trong trường hợp này; chỉ trong các lớp dẫn xuất có thể thậm chí không biết giao diện nào chúng đang thực hiện) – Rob

+2

Trong vb.net , người ta có thể nói: 'Protected Overridable Sub DoSomethingImpl() Thực hiện IDoSomething.DoSomething'; mã bên ngoài sẽ chỉ có thể gọi phương thức đó thông qua giao diện, nhưng một lớp dẫn xuất sẽ có thể ghi đè phương thức và, trong quá trình ghi đè, hãy gọi phương thức cha. Trong C#, nó sẽ hữu ích để có thể tương tự như vậy sử dụng một phương pháp được bảo vệ để thực hiện một giao diện, nhưng những người phụ trách spec không cho phép tùy chọn đó. Người gần nhất có thể đến sẽ thực hiện một cách rõ ràng giao diện với một phương thức gọi phương thức được bảo vệ 'DoSomethingImpl()'. Lưu ý rằng ... – supercat

20

Phương pháp phải được triển khai public vì chúng phải được gọi qua giao diện, do đó từ giao diện có thể truy cập dưới dạng loại.

Bạn có một vài tùy chọn ở đây để "thay đổi" khả năng hiển thị của phương thức đó. Đưa ra:

public interface IFoo 
{ 
    bool IsFoo(); 
} 

A. Thực hiện các phương pháp explicitly

public class Foo : IFoo 
{ 
    bool IFoo.IsFoo() { return true; } 
} 

Phương pháp này sẽ chỉ có sẵn thông qua giao diện

B. Thay đổi tầm nhìn của (IFoo trong trường hợp này.) giao diện

Xác định giao diện là internal thay vì public. Kết quả là, tuy nhiên, Foo cũng sẽ phải là internal.

+0

Trong các ngôn ngữ khác như như vb.net, không có khả năng truy cập cụ thể là cần thiết cho một phương pháp thực hiện một giao diện. C# yêu cầu rằng việc triển khai giao diện ngầm phải được công khai vì không có từ khóa hoặc ký hiệu nào khác để chỉ ra rằng một thành viên lớp được đặt tên cũng nên được coi là một triển khai giao diện. – supercat

5

Yêu cầu triển khai giao diện là công khai chỉ đơn giản là yêu cầu hợp lý. Khi bạn thực hiện một giao diện, bạn đang nói với trình biên dịch "Hey tôi thực hiện mọi phương thức trên giao diện này". Vì vậy, làm cho phương thức riêng tư làm cho nó không thể truy cập được nữa - và không được thực hiện một cách hợp lý. Giao diện phục vụ như là một hợp đồng để mã sử dụng đối tượng của bạn nói rằng bạn luôn có thể gọi bất kỳ phương pháp được xác định trong giao diện trên đối tượng của tôi. Nếu phương pháp triển khai là riêng tư, điều đó sẽ không còn đúng nữa.

Nếu bạn muốn ẩn triển khai của mình, hãy nói Intellisense, thì bạn có thể chỉ cần triển khai phương thức một cách rõ ràng như @Bryan đề cập.

+0

"Giao diện phục vụ như một hợp đồng để mã sử dụng đối tượng của bạn nói rằng bạn luôn có thể gọi bất kỳ phương pháp được xác định trong giao diện trên đối tượng của tôi." Điều đó không đúng. Nó có nghĩa là bạn có thể truyền một thể hiện của lớp tới giao diện và _then_ gọi các phương thức giao diện thông qua tham chiếu giao diện. R isNG là hợp đồng, KHÔNG có khả năng gọi các phương thức của giao diện mà không cần truyền đầu tiên tới giao diện. Tất nhiên bạn nên thường phơi bày các phương thức giao diện mà không yêu cầu dàn diễn viên, nhưng đó không phải là yêu cầu kỹ thuật cũng không phải luôn là yêu cầu hợp lý. – Darryl

Các vấn đề liên quan