public interface Foo {
}
public class SpecificFoo implements Foo {
}
public interface SomeInterface {
void thisMethod(Foo someKindOfFoo);
}
public class SomeClass implements SomeInterface {
public void thisMethod(Foo someKindOfFoo) {
// calling code goes into this function
System.out.println("Dont go here please");
}
public void thisMethod(SpecificFoo specificFoo) {
// not into this function
System.out.println("Go here please");
}
}
public class SomeOlderClass {
public SomeOlderClass( SomeInterface inInterface ) {
SpecificFoo myFoo = new SpecificFoo();
inInterface.thisMethod(myFoo);
}
}
телефонный код:
SomeClass myClass = new SomeClass();
SomeOlderClass olderClass = new SomeOlderClass(myClass);
У меня есть интерфейс (SomeInterface
), к которому обращаются несколько классов (например, SomeOlderClass
). У меня есть класс, который реализует интерфейс, но я хочу делать безопасные операции над типами в конкретных реализациях, которые передаются в общий интерфейс.
Как показано в приведенном выше коде, я действительно хочу иметь возможность создать другой метод, который соответствует конкретному типу, передаваемому интерфейсу. Это не работает Я предполагаю, что это потому, что вызывающий код знает только об интерфейсе, а не о реализации с более конкретными методами (даже если SpecificFoo implements Foo
)
Так как я могу сделать это самым элегантным способом? Я могу заставить код работать, добавив оператор if в класс, реализующий интерфейс (SomeClass
):
public void thisMethod(Foo someKindOfFoo) {
// calling code goes into this function
if ( someKindOfFoo.getClass().equals(SpecificFoo.class) )
thisMethod(SpecificFoo.class.cast(someKindOfFoo));
else
System.out.println("Dont go here please");
}
Однако это не элегантно, так как я должен добавлять операторы if каждый раз, когда я добавляю новый тип Foo. И я могу забыть сделать это.
Другой вариант - добавить SpecificFoo
к SomeInterface
и позволить компилятору разобраться, напомнив мне, что мне нужны реализации в SomeClass
. Проблема с этим заключается в том, что я добавляю совсем немного кода для котельной плиты. (Если кто-то еще реализует интерфейс, он должен реализовать новый метод, а также любые тесты)
Кажется, должен быть другой вариант, который мне не хватает, учитывая, что Foo
и SpecificFoo
связаны между собой. Идеи?
ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ:
Ну, я действительно некоторое время работал, чтобы попытаться упростить вопрос. Поскольку я добавляю больше деталей, сложность возрастает совсем немного. Но что бы ... я думаю, я могу это объяснить.
По сути, я пишу сервлет RPC веб-приложений GWT, используя шаблон команды, как объяснил Рэй Райан в своем выступлении
Существует несколько реализаций этого в коде Google, но многие из них страдают от этой проблемы наследования. Я думал, что это ошибка в коде GWT-RPC bugreport ОДНАКО, по мере реализации я заметил, что аналогичная проблема возникает исключительно на стороне клиента и в режиме хостинга. (т. е. все Java, без GWT Javascript безумие).
Итак, я абстрагировал основные идеи в случае командной строки исходного кода Java и увидел ту же проблему, как описано выше.
Если вы следуете тому, что обсуждает Рэй Райан, Foo
- это Действие, SpecificFoo
- это конкретное действие, которое я хочу вызвать. SomeInterface
- это RPC-сервис на стороне клиента, а SomeClass
- RPC-класс на стороне сервера. SomeOlderClass
- это разновидность службы rpc, которая знает о кешировании и прочем.
Очевидно, верно? Ну, как я уже сказал, я думаю, что вся ерунда GWT RPC только запутывает воду в базовом вопросе, поэтому я попытался упростить ее настолько, насколько мог.