Tôi sử dụng thực hiện giao diện rõ ràng hầu hết thời gian. Dưới đây là những lý do chính.
Tái cấu trúc là an toàn hơn
Khi thay đổi một giao diện, sẽ tốt hơn nếu trình biên dịch có thể kiểm tra nó. Điều này là khó khăn hơn với việc thực hiện ngầm.
Hai trường hợp phổ biến đến với tâm trí:
Thêm một chức năng vào một giao diện, trong đó một lớp hiện có thực hiện giao diện này đã có một phương thức có cùng chữ ký với giao diện mới . Điều này có thể dẫn đến hành vi bất ngờ, và đã cắn tôi nhiều lần. Thật khó để "nhìn thấy" khi gỡ lỗi vì chức năng đó có thể không nằm trong các phương thức giao diện khác trong tệp (vấn đề tự ghi lại được đề cập dưới đây).
Loại bỏ một chức năng từ một giao diện . Các phương thức được triển khai ngầm sẽ đột nhiên là mã chết, nhưng các phương thức được triển khai rõ ràng sẽ bị bắt bởi lỗi biên dịch. Ngay cả khi mã chết là tốt để giữ xung quanh, tôi muốn bị buộc phải xem lại và quảng bá nó.
Thật không may là C # không có từ khóa buộc chúng ta phải đánh dấu một phương thức là một triển khai ngầm, vì vậy trình biên dịch có thể thực hiện các kiểm tra bổ sung. Các phương thức ảo không có một trong các vấn đề nêu trên do yêu cầu sử dụng 'ghi đè' và 'mới'.
Lưu ý: đối với các giao diện cố định hoặc hiếm khi thay đổi (thường là từ API của nhà cung cấp), đây không phải là vấn đề. Tuy nhiên, đối với các giao diện của riêng tôi, tôi không thể dự đoán khi nào / chúng sẽ thay đổi như thế nào.
Đó là tài liệu tự
Nếu tôi thấy 'công khai bool Execute ()' trong một lớp, nó sẽ mất thêm công việc để tìm ra rằng đó là một phần của giao diện. Ai đó có thể sẽ phải bình luận nó nói như vậy, hoặc đặt nó trong một nhóm các triển khai giao diện khác, tất cả dưới một khu vực hoặc nhóm nhận xét nói "triển khai ITask". Tất nhiên, điều đó chỉ hoạt động nếu tiêu đề nhóm không ở ngoài màn hình ..
Trong khi đó: 'bool ITask.Execute ()' rõ ràng và không mơ hồ.
Phân tách rõ ràng thực hiện giao diện
Tôi nghĩ rằng các giao diện là 'công khai' hơn các phương thức công cộng vì chúng được chế tạo để chỉ lộ ra một chút diện tích bề mặt của loại bê tông. Họ giảm loại thành khả năng, hành vi, tập hợp các đặc điểm, v.v. Và trong quá trình thực hiện, tôi nghĩ việc giữ sự tách biệt này là hữu ích.
Khi tôi đang xem qua mã của một lớp, khi tôi bắt gặp các triển khai giao diện rõ ràng, não tôi chuyển sang chế độ "hợp đồng mã". Thông thường các triển khai này chỉ đơn giản chuyển tiếp sang các phương thức khác, nhưng đôi khi chúng sẽ thực hiện kiểm tra trạng thái / param bổ sung, chuyển đổi các tham số đến để phù hợp hơn với các yêu cầu nội bộ hoặc thậm chí dịch cho các mục đích phiên bản (nghĩa là nhiều thế hệ giao diện chuyển sang triển khai chung).
(Tôi nhận ra rằng công chúng cũng là hợp đồng mã, nhưng giao diện mạnh hơn nhiều, đặc biệt là trong một cơ sở mã điều khiển giao diện nơi sử dụng trực tiếp các loại cụ thể thường là dấu hiệu của mã chỉ nội bộ.)
Liên quan: Lý do 2 ở trên của Jon .
Và như thế
Cộng với những lợi thế đã được đề cập trong các câu trả lời khác ở đây:
Các vấn đề
Đó không phải là tất cả niềm vui và hạnh phúc. Có một số trường hợp tôi dính vào ẩn ý:
- Các loại giá trị, bởi vì điều đó sẽ đòi hỏi quyền anh và sự hoàn hảo thấp hơn. Đây không phải là một quy tắc nghiêm ngặt và phụ thuộc vào giao diện và cách sử dụng. Có thể cạnh tranh? Ngụ ý. Có thể khử được? Có lẽ rõ ràng.
- Các giao diện hệ thống tầm thường có các phương thức thường được gọi trực tiếp (như IDisftime.Dispose).
Ngoài ra, có thể là một khó khăn khi thực hiện việc đúc khi bạn thực tế có loại cụ thể và muốn gọi một phương thức giao diện rõ ràng. Tôi giải quyết vấn đề này theo một trong hai cách:
- Thêm công chúng và có các phương thức giao diện chuyển tiếp cho họ để thực hiện. Thông thường xảy ra với các giao diện đơn giản hơn khi làm việc nội bộ.
- (Phương pháp ưa thích của tôi) Thêm một
public IMyInterface I { get { return this; } }
(cần được nội tuyến) và gọi foo.I.InterfaceMethod()
. Nếu nhiều giao diện cần khả năng này, hãy mở rộng tên ngoài tôi (theo kinh nghiệm của tôi, hiếm khi tôi có nhu cầu này).