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ó" I1
và I2
vào I3
Mờ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 : I3
tương đương với : I1, I2
, : I1, I2
khô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 I1
và I2
sẽ 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 I1
và I2
ngụ ý 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 something
hiệ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 foo
sẽ lấy thứ gì đó thực hiện I1
và 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ì foo
quan 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, I1
phầ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.