Giả sử bạn có hai giao diện:
interface Readable {
public void read();
}
interface Writable {
public void write();
}
Trong một số trường hợp, các đối tượng triển khai chỉ có thể hỗ trợ một trong những điều này nhưng trong rất nhiều trường hợp, việc triển khai sẽ hỗ trợ cả hai giao diện. Những người sử dụng các giao diện sẽ phải làm một cái gì đó như:
// can't write to it without explicit casting
Readable myObject = new MyObject();
// can't read from it without explicit casting
Writable myObject = new MyObject();
// tight coupling to actual implementation
MyObject myObject = new MyObject();
Không có tùy chọn nào trong số này là thuận tiện khủng khiếp, thậm chí còn nhiều hơn khi xem xét rằng bạn muốn đây là một tham số phương thức.
Một giải pháp sẽ là khai báo giao diện gói:
interface TheWholeShabam extends Readable, Writable {}
Nhưng điều này có một vấn đề cụ thể: tất cả các triển khai hỗ trợ cả Readable và Writable đều phải triển khai TheWholeShabam nếu chúng muốn tương thích với mọi người sử dụng giao diện. Mặc dù nó không cung cấp gì ngoài sự hiện diện được đảm bảo của cả hai giao diện.
Có một giải pháp rõ ràng cho vấn đề này hay tôi nên sử dụng giao diện trình bao bọc?
CẬP NHẬT
Trên thực tế, thường là cần thiết để có một đối tượng vừa có thể đọc vừa có thể ghi được, vì vậy chỉ cần tách biệt các mối quan tâm trong các đối số không phải lúc nào cũng là một giải pháp sạch.
CẬP NHẬT2
(được trích xuất dưới dạng câu trả lời để dễ nhận xét hơn)
CẬP NHẬT3
Xin lưu ý rằng usecase chính cho việc này là không phải luồng (mặc dù chúng cũng phải được hỗ trợ). Các luồng tạo ra sự phân biệt rất cụ thể giữa đầu vào và đầu ra và có sự phân tách trách nhiệm rõ ràng. Thay vào đó, hãy nghĩ về một cái gì đó giống như một bytebuffer nơi bạn cần một đối tượng bạn có thể viết và đọc từ đó, một đối tượng có trạng thái rất cụ thể gắn liền với nó. Các đối tượng này tồn tại bởi vì chúng rất hữu ích cho một số thứ như I / O không đồng bộ, mã hóa, ...
CẬP NHẬT4
Một trong những điều đầu tiên tôi đã thử giống như gợi ý được đưa ra dưới đây (kiểm tra câu trả lời được chấp nhận) nhưng nó tỏ ra quá mong manh.
Giả sử bạn có một lớp phải trả về kiểu:
public <RW extends Readable & Writable> RW getItAll();
Nếu bạn gọi phương thức này, RW chung được xác định bởi biến nhận đối tượng, vì vậy bạn cần một cách để mô tả var này.
MyObject myObject = someInstance.getItAll();
Điều này sẽ hoạt động nhưng một lần nữa liên kết nó với một triển khai và thực sự có thể ném các ngoại lệ classcast khi chạy (tùy thuộc vào những gì được trả về).
Ngoài ra, nếu bạn muốn một biến lớp thuộc loại RW, bạn cần xác định chung ở cấp độ lớp.