2010-01-29 40 views
8

Tôi mới sử dụng OOP và có một số câu hỏi.Giao diện trong C#

  1. Tại sao các phương thức được khai báo trong giao diện có công cụ sửa đổi (công khai, riêng tư, v.v.).

  2. Trong mã này:

class Program 
{ 
    static void Main(string[] args) 
    { 
     X ob = new Y(); 
     ob.add(4, 5); 
     Z ob1 = new Y(); 
     ob1.mull(2, 3); 
     Console.Read(); 
    } 
} 

public interface X 
{ 
    void add(int x, int y); 
} 
public interface Z 
{ 
    void mull(int x, int y); 
} 

class Y : X, Z 
{ 
    void X.add(int x, int y)//here we are not decalring it as public ,why? 
    { 
     Console.WriteLine("sum of X and y is " + (x + y)); 
    } 
    void Z.mull(int x, int y) 
    { 
     Console.WriteLine("product of X and Y is" + (x * y)); 
    } 
} 

Cả hai phương pháp này không đòi hỏi phải bổ nhưng khi tôi không sử dụng giao diện, như X.add() trên, tôi cần phải thực hiện các công việc thực hiện. Tại sao?

+0

có thể trùng lặp của http://stackoverflow.com/questions/1652123/is-there-a-reason-you-can-not-define-the-access-modifier-on-a-method-or-in- an-int –

Trả lời

1

Vì các thành viên giao diện được tự động công khai. Bạn đang xác định một hợp đồng thông qua một giao diện, và nó sẽ không có ý nghĩa gì đối với các thành viên không được công khai, vì bạn phải thực hiện chúng trong lớp thực hiện của bạn.

34

Giao diện là hợp đồng. Nó nói "Tôi có thể làm những việc này." Điểm của ai đó giao cho bạn một bản sao của IInterface trong đó bạn không thể sử dụng một số phương pháp trong hợp đồng đó vì chúng đã được đánh dấu là không công khai?

Đây là lý do thiết kế ngôn ngữ theo cách này. Thông số kỹ thuật cho điều này là trong §13.2 của đặc tả ngôn ngữ:

Mọi thành viên giao diện đều có quyền truy cập công cộng. Đó là một lỗi biên dịch thời gian cho các khai báo thành viên giao diện bao gồm bất kỳ công cụ sửa đổi nào. Cụ thể, không thể khai báo thành viên giao diện với các công cụ sửa đổi abstract, public, protected, internal, private,virtual, override hoặc static.

Đối với mã của bạn, đó là ví dụ về explicit interface implementation. Nó là hữu ích nhất khi một lớp hoặc cấu trúc triển khai thực hiện hai giao diện với mỗi thành viên có cùng một chữ ký. Ví dụ: cả hai số IEnumerableIEnumerable<T> xác định phương thức GetEnumerator không chấp nhận tham số.

public interface IEnumerable { 
    IEnumerator GetEnumerator(); 
} 

public interface IEnumerable<T> : IEnumerable { 
    IEnumerator<T> GetEnumerator(); 
} 

Lưu ý rằng bằng cách định nghĩa ở trên, bất kỳ lớp mà thực hiện IEnumerable<T> cũng phải thực hiện IEnumerable. Hãy nhớ rằng loại trả lại không phải là một phần của chữ ký và do đó chúng tôi có xung đột với IEnumerable.GetEnumeratorIEnumerable<T>.GetEnumerator. Đây là cách triển khai giao diện rõ ràng nhằm giải quyết:

class X<T> : IEnumerable<T> { 
    List<T> _list = new List<T>(); 
    public IEnumerator<T> GetEnumerator() { 
     return _list.GetEnumerator(); 
    } 

    IEnumerator GetEnumerator() { 
     return GetEnumerator(); // invokes IEnumerable<T>.GetEnumerator 
    } 
} 

Thành viên thực hiện giao diện rõ ràng chỉ hiển thị thông qua giao diện của giao diện. Như vậy:

X<int> x = new X<int>(); 
var e1 = x.GetEnumerator(); // invokes IEnumerable<int>.GetEnumerator 
          // IEnumerable.GetEnumerator is not visible 
IEnumerable y = x; 
var e2 = y.GetEnumerator(); // invokes IEnumerable.GetEnumerator 

Như vậy, trong mã của bạn

X ob = new Y(); 
ob.add(1, 2); // X.add is visible through interface 
Y y = new Y(); 
y.add(1, 2); // compile-time error, X.add is not visible 

Cả hai phương pháp này không đòi hỏi phải bổ nhưng khi tôi không sử dụng giao diện, như X.add() ở trên, tôi cần phải thực hiện công khai. Tại sao?

OK, không rõ chính xác những gì bạn đang yêu cầu ở đây. Công cụ sửa đổi truy cập không được phép cho việc triển khai giao diện rõ ràng. Đây là 13,4:

Đó là một lỗi thời gian biên dịch cho một thực hiện thành viên giao diện rõ ràng bao gồm bổ truy cập, và nó là một lỗi thời gian biên dịch để bao gồm các bổ abstract, virtual, override, hoặc static.

Nếu triển khai giao diện không được đánh dấu là triển khai giao diện rõ ràng, thì phải có công cụ sửa đổi truy cập public. Đây là 13.4.4 (Giao diện lập bản đồ):

Giao diện bản đồ cho một lớp học hoặc struct C nằm một thực hiện cho mỗi thành viên của mỗi giao diện được quy định trong danh sách lớp cơ sở của C. Việc thực hiện một thành viên giao diện cụ thể I.M, trong đó I là giao diện trong đó thành viên M được khai báo, được xác định bằng cách kiểm tra từng lớp hoặc cấu trúc S, bắt đầu bằng C và lặp lại cho mỗi lớp cơ sở liên tiếp C.

  • Nếu S chứa một tuyên bố của một thực hiện thành viên giao diện rõ ràng phù hợp với IM, sau đó thành viên này là việc thực hiện I.M

  • Nếu không, nếu S chứa tuyên bố của thành viên công cộng không tĩnh khớp với M thì thành viên này sẽ triển khai I.M.

Lỗi biên dịch xảy ra nếu không thể định vị cho tất cả thành viên của tất cả các giao diện được chỉ định trong danh sách lớp cơ sở C.

Vì vậy, trong ngắn hạn, trình biên dịch đầu tiên tìm kiếm triển khai giao diện rõ ràng. Nếu nó không thể tìm thấy một thì nó tìm kiếm không tĩnh, công khai thành viên có chữ ký giống như phương pháp M đang được triển khai. Nếu nó không thể tìm thấy một lỗi biên dịch thời gian xảy ra. Vì vậy, các quy tắc là điều này.Để thực hiện một thành viên giao diện I.M:

  1. Nếu bạn thực hiện một cách rõ ràng I.M thì cú pháp là

    return-type I.M(parameter-list)

  2. Nếu không, cú pháp là

    public return-type M(parameter-list)

Như vậy, với

Chúng tôi có thể thực hiện một cách rõ ràng:

class Explicit : IAdd { 
    int IAdd.Add(int x, int y) { return x + y; } 
} 

hay không:

class NotExplicit : IAdd { 
    public int Add(int x, int y) { return x + y; } 
} 

Sự khác biệt là sau đó rằng Explicit.Add là không hiển thị trừ trường hợp của Explicit đang gõ như IAdd :

IAdd explicitInterface = new Explicit(); 
explicitInterface.Add(2, 2); 
Explicit explicit = new Explicit(); 
explicit.Add(2, 2); // compile-time error 

trong khi

IAdd notExplicitInterface = new NotExplicit(); 
notExplicitInterface.Add(2, 2); 
NotExplicit notExplicit = new NotExplicit(); 
notExplicit.Add(2, 2); // okay, NOT a compile-time error as above 

Điều đó giúp đỡ?

+6

Câu trả lời này rất điên rồ. –

+0

Phải có điều gì đó thiếu trong câu trả lời ngắn của bạn. Tôi vẫn đang tìm kiếm ... –

1

Trực tiếp từ Microsoft: "Các thành viên Interface luôn công vì mục đích của giao diện là để cho phép các loại khác để truy cập một lớp hoặc cấu trúc. "

+0

Bạn có thể muốn sửa các liên kết của mình. –

+0

Điều này đã được sửa, thx. – alchemical

0

Vì chức năng, trường v.v. được khai báo trong Giao diện luôn có công cụ sửa đổi công khai theo mặc định. Vì vậy, khi thực hiện nó, bạn không cần phải gõ công khai vì lớp đã có phương pháp bây giờ là giao diện thực hiện công khai của nó. Trong tất cả các lớp, tất cả các trường và phương thức đều là privete nhưng bị điếc.

1

Vì hai giao diện của bạn không xác định phương thức có cùng chữ ký, bạn không cần triển khai rõ ràng. Bạn có thể thực hiện các thao tác sau:

public void add(int x, int y) 
{ 
    Console.WriteLine("sum of X and y is " + (x + y)); 
} 
public void mull(int x, int y) 
{ 
    Console.WriteLine("product of X and Y is" + (x * y)); 
} 

Đó là thực hiện ngầm định giao diện và giờ đây dễ dàng gọi những phương thức đó trên trường hợp của lớp học. Chỉ cần gọi myInstance.add(1, 2) thay vì phải truyền myInstance làm phiên bản giao diện X.

0

Đây là sự khác biệt giữa việc thực hiện giao diện ExplictImplict.

Bạn thường muốn triển khai giao diện ngầm, nghĩa là các thành viên đã triển khai được cung cấp công khai. Điều này có ý nghĩa khi bạn xem xét việc thực hiện một giao diện thường biểu thị rằng một lớp có thể thực hiện một tính năng cụ thể (chẳng hạn như được xử lý thông qua IDisposable).

Trong trường hợp bạn cần loại để triển khai giao diện nhưng không muốn các thành viên giao diện đó có thể truy cập công khai, bạn sử dụng triển khai rõ ràng. Các thành viên vẫn có thể truy cập, nhưng chỉ khi tham chiếu loại thông qua giao diện.

1

Tôi sẽ sao lưu và giải thích các triệu chứng bạn đang báo cáo thay vì cố gắng giải thích tại sao công cụ sửa đổi là không cần thiết; các câu trả lời khác đã giải thích đầy đủ.

Có lẽ lý do bạn nhầm lẫn là bạn đang sử dụng triển khai giao diện rõ ràng. Khi bạn sử dụng thực hiện giao diện rõ ràng, bạn cần phải truyền đối tượng đối tượng đến kiểu giao diện đó trước khi bạn có thể gọi các phương thức của nó.

Nếu bạn xóa "X." từ việc triển khai X.Add của bạn, bạn sẽ có thể "xem" và sử dụng giao diện mà không có diễn viên rõ ràng. Đây là triển khai giao diện "ngầm". Miễn là bạn không có bất kỳ va chạm tên nào, hoặc một số lý do để làm cho các thành viên giao diện hơi ít nhìn thấy được đối với các máy khách bình thường, bạn có thể muốn thực hiện giao diện ngầm.