Bất cứ điều gì thực hiện I3 sẽ cần phải thực hiện I1 và I2, và các đối tượng từ các lớp khác nhau kế thừa I3 sau đó có thể được sử dụng thay thế cho nhau (xem bên dưới), vậy có đúng không khi gọi I3 trống? Nếu vậy điều gì sẽ là một cách tốt hơn để kiến trúc này?
"Đóng bó" I1và I2vào I3Mời một đẹp (?) Phím tắt, hoặc một số loại đường cú pháp cho bất cứ nơi nào bạn muốn cả hai được thực hiện.
Vấn đề với cách tiếp cận này là bạn không thể ngăn các nhà phát triển khác triển khai rõ ràng I1 và I2 sát cánh bên nhau, nhưng nó không hoạt động theo cả hai cách - trong khi : I3tương đương với : I1, I2, : I1, I2không tương đương : I3. Ngay cả khi chúng giống nhau về mặt chức năng, một lớp hỗ trợ cả hai I1và I2sẽ không bị phát hiện là hỗ trợ I3.
Điều này có nghĩa là bạn đang cung cấp hai cách để hoàn thành cùng một thứ - "thủ công" và "ngọt ngào" (với đường cú pháp của bạn). Và nó có thể có tác động xấu đến tính nhất quán của mã. Cung cấp 2 cách khác nhau để thực hiện điều tương tự ở đây, ở đó và ở một nơi khác dẫn đến 8 kết hợp có thể có :)
void foo() {
I1 something = new A();
something = new B();
something.SomeI1Function();
something.SomeI2Function(); // we can't do this without casting first
}
OK, bạn không thể. Nhưng có lẽ đó thực sự là một dấu hiệu tốt?
Nếu I1và I2ngụ ý các trách nhiệm khác nhau (nếu không sẽ không cần phải tách chúng ra ngay từ đầu), thì có lẽ đã foo()sai khi thử và thực somethinghiện hai trách nhiệm khác nhau trong một lần?
Nói cách khác, có thể foo()chính nó đã vi phạm nguyên tắc Trách nhiệm đơn lẻ và thực tế là nó yêu cầu kiểm tra kiểu đúc và thời gian chạy để kéo nó ra là một lá cờ đỏ báo động cho chúng ta về nó.
BIÊN TẬP:
Nếu bạn khăng khăng đảm bảo foosẽ lấy thứ gì đó thực hiện I1và I2, bạn có thể chuyển chúng dưới dạng tham số riêng biệt:
void foo(I1 i1, I2 i2)
Và họ có thể là cùng một đối tượng:
foo(something, something);
Điều gì fooquan tâm nếu họ là cùng một ví dụ hay không?
Nhưng nếu nó không quan tâm (ví dụ: vì chúng không phải là không quốc tịch) hoặc bạn chỉ nghĩ rằng điều này trông xấu, thì người ta có thể sử dụng thuốc generic thay thế:
void Foo<T>(T something) where T: I1, I2
Bây giờ các ràng buộc chung sẽ chăm sóc hiệu ứng mong muốn trong khi không gây ô nhiễm thế giới bên ngoài với bất cứ điều gì. Đây là C # thành ngữ, dựa trên kiểm tra thời gian biên dịch, và nó cảm thấy đúng hơn về tổng thể.
Tôi thấy I3 : I2, I1phần nào là một nỗ lực để mô phỏng các loại kết hợp trong một ngôn ngữ không hỗ trợ nó ra khỏi hộp (C # hoặc Java thì không, trong khi các loại kết hợp tồn tại trong các ngôn ngữ chức năng).
Cố gắng mô phỏng một cấu trúc không thực sự được hỗ trợ bởi ngôn ngữ thường rất khó hiểu. Tương tự, trong C #, bạn có thể sử dụng các phương thức và giao diện mở rộng nếu bạn muốn mô phỏng mixins . Khả thi? Đúng. Ý tưởng tốt? Tôi không chắc.