Припустимо, у вас є два інтерфейси:
interface Readable {
public void read();
}
interface Writable {
public void write();
}
У деяких випадках об'єкти, що реалізують, можуть підтримувати лише один із них, але у багатьох випадках реалізація підтримує обидва інтерфейси. Люди, які використовують інтерфейси, повинні зробити щось на кшталт:
// 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();
Жоден із цих варіантів не є надзвичайно зручним, тим більше, якщо врахувати, що ви хочете це як параметр методу.
Одним із варіантів рішення було б оголосити обгортковий інтерфейс:
interface TheWholeShabam extends Readable, Writable {}
Але в цьому є одна конкретна проблема: всі реалізації, які підтримують і читабельні, і записувані, повинні реалізувати TheWholeShabam, якщо вони хочуть бути сумісними з людьми, які використовують інтерфейс. Хоча він не пропонує нічого, крім гарантованої присутності обох інтерфейсів.
Чи є чітке рішення цієї проблеми чи мені слід перейти до інтерфейсу обгортки?
ОНОВЛЕННЯ
Насправді часто потрібно мати об'єкт, який читається і записується, тому просто відокремлення проблем у аргументах не завжди є чистим рішенням.
ОНОВЛЕННЯ2
(витягується як відповідь, тому простіше коментувати)
ОНОВЛЕННЯ3
Будь ласка, майте на увазі, що основним шаблоном для цього є не потоки (хоча вони теж повинні підтримуватися). Потоки дуже чітко розмежовують вхід і вихід, і чіткий розподіл обов'язків. Скоріше, придумайте щось на зразок байт-буфера, де вам потрібен один об'єкт, з якого ви можете писати та читати, один об’єкт, який має до нього дуже специфічний стан. Ці об'єкти існують, оскільки вони дуже корисні для таких речей, як асинхронний введення / виведення, кодування, ...
ОНОВЛЕННЯ4
Однією з перших речей, які я спробував, було те саме, що запропоновано нижче (перевірити прийняту відповідь), але виявилося занадто крихким.
Припустимо, у вас є клас, який повинен повернути тип:
public <RW extends Readable & Writable> RW getItAll();
Якщо ви викликаєте цей метод, загальний RW визначається змінною, що приймає об'єкт, тому вам потрібен спосіб описати цей var.
MyObject myObject = someInstance.getItAll();
Це буде працювати, але ще раз прив’язує його до реалізації та може фактично кидати classcastexceptions під час виконання (залежно від того, що повертається).
Крім того, якщо ви хочете змінну класу типу RW, вам потрібно визначити загальну на рівні класу.