У меня есть следующие настройки определяются следующим образом:Как сделать шаблон посетителя более расширяемым, создав элементы подтипа, требующим определенных посетителей подтипа через дженерики?
public interface Element {
public <R> R accept(Visitor<R> visitor);
}
public interface Visitor<R> {
}
class SpecificElement implements Element {
@Override // ERROR: didn't override accept in parent
public <R> R accept(SpecificVisitor visitor) {
return visitor.visitSpecificElement(this);
}
}
class SpecificVisitor implements Visitor<Boolean> {
public Boolean visitSpecificElement(SpecificElement element) {
return true;
}
}
Как я могу изменить настройки выше, так что я могу требовать подтипа SpecificElement
только принимать SpecificVisitor
и возможности переопределить родительский класс accept
метода.
То, что я хочу, чтобы это произошло, чтобы санкционировать, что класс реализации SpecificElement
будет принимать только гостей типа SpecificVisitor
и ничего, но по-прежнему держать подпись интерфейса типа Element
«s на Visitor
.
UPDATE 1: я добавил параметр типа V extends Visitor<?>
в Element
, а затем расширить его SpecificElement extends Element<SpecificVisitor<?>
и был в состоянии получить то, что я хочу (более строгие типы параметров в методе принимают): <R> R accept(SpecificVisitor<?> visitor)
. Однако теперь моя проблема заключается в том, что я хочу определить возвращаемый тип метода accept
на основе параметра типа посетителя аргумента (в данном случае ?
). Изменение ?
на R
вызывает ошибку компиляции.
public interface Element<V extends Visitor<?> {
public <R> R accept(Visitor<R> visitor);
}
public interface Visitor<R> {
}
class SpecificElement implements Element<SpecificVisitor<?>> {
@Override
public <R> R accept(SpecificVisitor<R> visitor) { // error in type parameter R in SpecificVisitor
return visitor.visitSpecificElement(this);
}
}
class SpecificVisitor implements Visitor<Boolean> {
public Boolean visitSpecificElement(SpecificElement element) {
return true;
}
}
UPDATE 2: Я хотел бы написать семейство посетителей для семьи элементов, не отказываясь от типобезопасности. Обратите внимание на использование одного и того же подтипа Visitor для поддерева Element. Пример:
--- Element -> Visitor<R>
|
|---- SpecificElement -> SpecificVisitor<R>
| |
| |---------SpecificElementA -> SpecificVisitor<R>
| |
| |---------SpecificElementB -> SpecificVisitor<R>
|
|---- FancyElement -> FancyVisitor<R>
|
|---------FancyElementA -> FancyVisitor<R>
|
|---------FancyElementB -> FancyVisitor<R>
Я не уверен, есть ли хорошее решение для этого без множественных ограничений типа, которые включают переменные типа или более высокие типы, ни одна из которых не поддерживается Java. –
Возможно, это поможет людям найти подходящие обходы, если вы включили информацию или примеры того, как это будет полезно? (По сравнению с простым определением 'SpecificElement' и' SpecificVisitor' без суперклассов.) –
@DanGetz В настоящее время я склонен думать, что это не поддерживается в Java. Но я добавил больше объяснений относительно того, что я хочу, чтобы произойти выше. – Chad