Tôi đang phát triển một số mã sử dụng thuốc generic và một trong những nguyên tắc hướng dẫn của tôi là làm cho nó có thể sử dụng được cho các tình huống trong tương lai, và không chỉ ngày nay. Tuy nhiên, một số đồng nghiệp đã bày tỏ rằng tôi có thể đã đánh đổi khả năng đọc vì lợi ích của khả năng mở rộng. Tôi muốn thu thập một số phản hồi về các cách có thể để giải quyết điều này.
Cụ thể, đây là một giao diện xác định một biến đổi - bạn bắt đầu với một bộ sưu tập các mục nguồn và bạn áp dụng biến đổi cho từng thành phần, lưu trữ các kết quả trong một bộ sưu tập đích. Ngoài ra, tôi muốn có thể trả lại bộ sưu tập đích cho người gọi và thay vì buộc họ sử dụng tham chiếu Bộ sưu tập, tôi muốn họ có thể sử dụng bất kỳ loại bộ sưu tập nào họ thực sự cung cấp cho bộ sưu tập đích.
Cuối cùng, tôi làm cho loại vật phẩm trong bộ sưu tập đích có thể khác với loại vật phẩm trong bộ sưu tập nguồn, bởi vì có lẽ đó là những gì biến đổi làm được. Ví dụ, trong mã của tôi, một số mục nguồn tạo nên một mục đích sau khi chuyển đổi.
Điều này mang lại giao diện sau:
interface Transform<Src, Dst> {
<DstColl extends Collection<? super Dst>> DstColl transform(
Collection<? extends Src> sourceCollection,
DstColl destinationCollection);
}
Tôi đã cố gắng trở nên tốt đẹp và áp dụng nguyên tắc PECS của Josh Bloch (nhà sản xuất mở rộng, siêu người tiêu dùng) để đảm bảo giao diện có thể sử dụng được với các loại siêu và phụ khi thích hợp. Kết quả cuối cùng là một phần của sự quái dị.
Bây giờ, thật tuyệt nếu tôi có thể mở rộng giao diện này và chuyên môn hóa nó bằng cách nào đó. Ví dụ: nếu tôi không thực sự quan tâm đến việc chơi đẹp với các kiểu con của các mục nguồn và siêu kiểu của các mục đích, tôi có thể có:
interface SimpleTransform<Src, Dst> {
<DstColl extends Collection<Dst>> DstColl transform(
Collection<Src> sourceCollection,
DstColl destinationCollection);
}
Nhưng không có cách nào để làm điều đó trong Java. Tôi muốn thực hiện giao diện này một cái gì đó mà những người khác thực sự sẽ xem xét làm, trái ngược với việc sợ hãi. Tôi đã xem xét một số tùy chọn:
- Đừng trả lại bộ sưu tập đích. Có vẻ kỳ lạ khi bạn thực hiện một biến đổi nhưng không nhận lại được gì.
- Có một lớp trừu tượng thực hiện giao diện này, nhưng sau đó chuyển các tham số sang một thứ dễ sử dụng hơn và gọi một phương thức khác là "translateImpl ()" có chữ ký đơn giản hơn và do đó giảm bớt gánh nặng nhận thức cho người thực hiện. Nhưng thật kỳ lạ khi phải viết một lớp trừu tượng chỉ để làm cho giao diện thân thiện với người dùng.
- Bỏ qua khả năng mở rộng và chỉ cần có giao diện đơn giản hơn. Có thể cặp đôi mà không trả lại bộ sưu tập đích. Nhưng sau đó điều đó giới hạn các lựa chọn của tôi trong tương lai.
Bạn nghĩ sao? Tôi có thiếu một cách tiếp cận tôi có thể sử dụng không?
Collection<? extends Src> srcCollection
, bạn nên sử dụngIterable<? extends Src>