Я борюсь с небольшой проблемой системы типа Java +, и, возможно, некоторые из вас вдохновлены решением этой проблемы.
Справочная информация:
Я реализую приложение Java, которое использует язык, специфичный для предметной области (DLS). DLS генерируется код и упакован с основным приложением. В конце концов, приложение должно поддерживать разные версии DSL.
На первый взгляд, это не проблема, поскольку разные версии DLS используют разные имена пакетов, ala *.sdtl.v2.*
и *.sdtl.v2.*.
Каждый из пакетов содержит все элементы, которые принадлежат DLS в текущей версии, например , синтаксический анализатор и элементы синтаксиса.
Проблема:
Моя проблема сейчас в том, что я хотел бы иметь какой-то переключатель для центральных элементов DSL, например, анализатор языка. Коммутатор должен, например, вернуть правильный анализатор для данной версии.
Пример:
class Parser {
public static Object forVersion(int version) {
switch (version) {
case 1:
return new *.stdl.v1.parser.Parser();
case 2:
return new *.stdl.v2.parser.Parser();
}
}
К сожалению, кажется невозможным найти значимую сигнатуру этого метода. Поскольку элементы DLS (например, класс Parser) являются сгенерированным кодом, и все версии этого класса не имеют общего суперкласса (кроме Object), очевидно, невозможно найти тип возврата для этих методов, кроме Object.
Мой текущий обходной путь - это класс-оболочка для сгенерированных классов анализатора с общим суперклассом. Это позволяет мне придать этому методу более конкретный тип, однако он только переносит проблему на следующий уровень, поскольку возвращение синтаксического анализатора также является синтаксическим элементом, который относится к версии.
abstract class ParserWrapper {
final int version;
protected ParserWrapper(int version) {
this.version = version;
}
public abstract Object parse(String string);
}
class STDLv1Wrapper extends ParserWrapper {
public Node parse(String string) {
return new *.stdl.v1.parser.Parser().parse(string);
}
}
class STDLv1Wrapper extends ParserWrapper {
public Node parse(String string) {
return new *.stdl.v2.parser.Parser().parse(string);
}
}
class Parser {
public static ParserWrapper forVersion(int version) {
switch (version) {
case 1:
return new STDLv1Wrapper();
case 2:
return new STDLv2Wrapper();
}
}
}
У кого-нибудь есть более изящное представление о том, как справиться с этой ситуацией?