Целью нашего подхода является внедрение интерфейсов в существующие классы DAO и модели. Классы модели идентифицируются с помощью идентификаторов ресурсов различных типов, а идентификаторы ресурсов - это не просто случайные числа, но несут семантику и поведение. Таким образом, мы должны представлять идентификаторы ресурсов объектами, а не примитивными типами.
Текущий подход для идентификаторов ресурсов:
interface ResourceId<T> {
T get();
}
class UserId implements ResourceId<String> {
public String get();
}
Текущий подход для наших ресурсов / моделей:
interface Resource<I extends ResourceId> {
I id();
}
class User implements Resource<UserId> {
public UserId id();
}
Я изо всех сил пытаюсь найти рабочее решение для наших классов DAO. Вот несколько подходов, которые я пробовал, но не смог:
=== Вариант 1 ===
не удается с:
error: > expected
несколько уровней универсальных типов кажутся запрещенными в Java
interface Dao<R extends Resource<I extends ResourceId>> {
R findById(I id);
void save(R u);
}
class UserDao implements Dao<User> {
public User findById(UserId id);
public void save(User u);
}
=== Вариант 2 ===
не удается с:
UserDao is not abstract and does not override abstract method <R>save(R) in Dao
Также Дао выглядит глупо. UserDao должен быть объектом Dao .
interface Dao<I extends ResourceId> {
<R extends Resource<I>> R findById(I id);
<R extends Resource<I>> void save(R u);
}
class UserDao implements Dao<UserId> {
public User findById(UserId id);
public void save(User u);
}
=== Вариант 3 ===
не удается с:
UserDao is not abstract and does not override abstract method <I>findById(I) in Dao
Даже если это сработало, я не привязан к ResourceId, фактически реализованному R.
interface Dao<R extends Resource> {
<I extends ResourceId> R findById(I id);
void save(R u);
}
class UserDao implements Dao<User> {
public User findById(UserId id);
public void save(User u);
}
=== Вариант 4 ===
компилирует.
Однако #findById в UserDao должен принимать универсальный параметр типа ResourceId вместо UserId. Кроме того, внутри реализации #findById мы должны были бы привести результат #get () к String.
Обычно проблема заключается в том, что тип ResourceId не связан с ResourceId, фактически реализованным в R.
interface Dao<R extends Resource> {
R findById(ResourceId id);
void save(R u);
}
class UserDao implements Dao<User> {
public User findById(ResourceId id);
public void save(User u);
}
=== Вариант 5 ===
компилирует.
Однако Dao выглядит глупо. Информация о том, какой ResourceId мы хотим использовать (т. Е. UserId), уже доступна при реализации Ресурса (т. Е. User). Нет ли более чистого пути?
interface Dao<R extends Resource, I extends ResourceId> {
R findById(I id);
void save(R u);
}
class UserDao implements Dao<User, UserId> {
public User findById(UserId id);
public void save(User u);
}
Есть идеи, как правильно решить эту проблему?