Sự khác biệt giữa việc thực hiện Giao diện rõ ràng hay ngầm định là gì?


64

Trong Visual Studio tôi có thể nhấp chuột phải vào một giao diện và chọn Thực hiện Giao diện hoặc Triển khai Giao diện một cách rõ ràng.

Ảnh chụp màn hình Visual Studio

public class Test : ITest
{
    public string Id // Generated by Implement Interface
    {
        get { throw new NotImplementedException(); }
    }

    string ITest.Id // Generated by Implement Interface Explicitly
    {
        get { throw new NotImplementedException(); }
    }
}

Sự khác biệt duy nhất tôi thấy giữa hai là tên Giao diện được thêm vào các thuộc tính và phương thức giao diện khi chúng được tạo nếu bạn chọn Thực hiện Giao diện một cách rõ ràng.

Tôi thấy nó làm cho mã dễ đọc hơn một chút vì tôi có thể thấy phương thức / thuộc tính đó đến từ đâu, tuy nhiên điều này có tạo ra sự khác biệt nào trong cách lớp được sử dụng hoặc biên dịch không? Và nó có thực sự quan trọng nếu tôi thực hiện các giao diện của mình ngầm hay rõ ràng không?

Câu trả lời:


51

Kiểm tra câu trả lời hàng đầu từ Andrew Barrett để biết "triển khai giao diện ngầm và rõ ràng" trên SO .

Về cơ bản:

  • Tiềm ẩn: bạn truy cập các phương thức và thuộc tính giao diện như thể chúng là một phần của lớp.
  • Rõ ràng: bạn chỉ có thể truy cập các phương thức và thuộc tính khi coi lớp là giao diện được triển khai.

Mã ví dụ:

Ngụ ý:

Test t = new Test();
t.Id; // OK
((ITest)t).Id; // OK

Rõ ràng:

Test t = new Test();
t.Id; // Not OK
((ITest)t).Id; // OK

Về mặt "khi nào" bạn phải triển khai một giao diện một cách rõ ràng, đó là khi lớp của bạn đã có một phương thức có cùng chữ ký với một trong các phương thức của giao diện của bạn hoặc khi lớp của bạn thực hiện một số giao diện chia sẻ các phương thức có cùng chữ ký nhưng hợp đồng không tương thích.


1
Tôi cũng thấy việc triển khai rõ ràng hữu ích để có một loại giao diện "ẩn" với các hoạt động không an toàn. Nó cũng làm cho các cuộc gọi đến các phương thức đó nổi bật hơn, đó là một điều tốt cho những thứ không an toàn.
Tamás Szelei

Cũng cần đề cập rằng có một chi phí hiệu năng để sử dụng các giao diện rõ ràng, vì nó cần phải đóng hộp / bỏ hộp đối tượng bất cứ khi nào bạn tham chiếu thuộc tính / phương thức. Vì điều này, tốt hơn là sử dụng các giao diện ngầm nếu có thể
Rachel

3
@Rachel: Theo như tôi biết rằng chi phí hiệu suất chỉ áp dụng cho các loại giá trị.
Groky

8

Cũng có một sự khác biệt trong cách bạn gọi phương thức.

Khi sử dụng triển khai giao diện rõ ràng , bạn phải sử dụng loại giao diện để gọi việc triển khai cụ thể đó.

Vì vậy, trong mã cuộc gọi, bạn sẽ cần sử dụng một biến loại ITestđể truy cập ITest.Id.

Bài viết Triển khai giao diện rõ ràng (Hướng dẫn lập trình C #) trên MSDN có một ví dụ hay.


4

Nó cho phép bạn thực hiện hai giao diện xác định cùng một phương thức. Tuy nhiên, nếu bạn thực hiện giao diện một cách rõ ràng, các phương thức chỉ có thể được truy cập khi biến được nhập vào giao diện rõ ràng đó.

Xem: Hướng dẫn thực hiện giao diện rõ ràng


4

EDIT: Không nên tạo sự khác biệt Bạn không nên làm điều đó trừ khi lớp của bạn thực hiện hai giao diện có cùng thuộc tính, vì bạn sẽ phải chuyển sang giao diện có liên quan trước khi bạn có thể truy cập thành viên:

public interface ITest
{
    string Id { get; }
}

public interface IAlsoTest
{
    string Id { get; }
}

public interface ITestToo
{
    int Id { get; }
}

public class Test : ITest, IAlsoTest
{
    // Valid implicit implementation of BOTH interfaces
    public string Id
    {
        get { throw new NotImplementedException(); }
    }
}

public class TestSeparately : ITest, ITestToo
{
    // This way we can do different things depending
    // on which interface the callee called from.
    string ITest.Id
    {
        get { throw new NotImplementedException(); }
    }

    int ITestToo.Id
    {
        get { throw new NotImplementedException(); }
    }
}

public class TestOuch
{
    public void DoStuff()
    {
        var ts = new TestSeparately();

        // Works
        Console.WriteLine(((ITest)ts).Id);

        // Works
        Console.WriteLine(((ITestToo)ts).Id);

        // Not valid! Which one did we want to call?
        Console.WriteLine(ts.Id);
    }
}

Việc sử dụng ví dụ giữ khi bạn triển khai rõ ràng một thành viên giao diện ngay cả khi bạn chỉ sử dụng một giao diện duy nhất (mà tôi luôn quên: S), vì vậy tôi sẽ cố gắng tránh việc triển khai rõ ràng bất cứ khi nào có thể, vì nó sẽ ẩn các thành viên lớp nếu họ ' không được chuyển sang đúng giao diện (khá khó hiểu).


3

Dựa trên câu trả lời của Jalaya,

  • Tiềm ẩn: bạn truy cập các phương thức và thuộc tính giao diện như thể chúng là một phần của lớp.
  • Rõ ràng: bạn chỉ có thể truy cập các phương thức và thuộc tính khi coi lớp là giao diện được triển khai.

nhập mô tả hình ảnh ở đây

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.