Передать несколько типов в качестве параметра в функции фильтра объекта Iterable в Xtend - PullRequest
0 голосов
/ 09 ноября 2019

Я использую интерфейс генератора DSL Xtext для генерации некоторых моделей на основе моего Xtext DSL. Это работает нормально, но сейчас я сталкиваюсь с небольшой проблемой при написании генератора. Я использую генератор для фильтрации правил, объявленных в моем Xtext DSL. Я делаю это, выбирая определенные Правила, а затем преобразую их в объект Iterable, который затем можно использовать для фильтрации по определенным типам (см. Части toIterable.filter() в моем коде ниже). Код ниже содержит цикл for, который сам по себе содержит 3 вложенных цикла. Эти вложенные циклы все фильтруют в одном конкретном виде Оператора Метода (типы, которые я объявил в моем DSL). Я хотел бы объединить эти 3 цикла for в один цикл for, передав 3 типа в качестве параметров в методе filter(). В этом случае будет один вложенный цикл for, в котором условие в идеале должно выглядеть примерно так:

for (eachMethodStatement : ifStatement.expression.eAllContents.toIterable.filter(StatementSort1, StatementSort2, StatementSort3)

Проблема в том, что метод filter() принимает только один аргумент (один тип), поэтому сейчас янужно написать три метода отправки с именем getDemand, которые в основном делают то же самое. Это работает прямо сейчас, но это вынуждает меня написать много шаблонного кода для каждого типа, который я хочу фильтровать.

Есть ли способ отфильтровать несколько типов (в одном для цикла), не создавая многостандартный код?

for (ifStatement : ifElseStatement.eAllContents.toIterable.filter(IfStatements)){
    for (persistenceFunction : ifStatement.expression.eAllContents.toIterable.filter(SingleLibraryPersistenceMethodStatement)) {
            expressionDemand += getDemand(persistenceFunction,resourceTable)                            
        }
    for (interfaceFunction : ifStatement.expression.eAllContents.toIterable.filter(SingleLibraryInterFaceMethodStatement)) {                    
            expressionDemand += getDemand(interfaceFunction,resourceTable)                          
        }
    for (businessFunction : ifStatement.expression.eAllContents.toIterable.filter(SingleLibraryBusinessMethodStatement)) {                  
            expressionDemand += getDemand(businessFunction,resourceTable)
        }
    for (persistenceFunction : ifStatement.expression.eAllContents.toIterable.filter(RelationalOperator)) {
            expressionDemand += getDemand(persistenceFunction,resourceTable)                            
        }
}

1 Ответ

0 голосов
/ 10 ноября 2019

<T> T filter(Class<T>) не может делать несколько типов, потому что тогда тип возвращаемого значения не может быть T, но - в крайнем случае Object, который должен быть приведен позже.

Но: если ваши четыре типа (SingleLibraryPersistenceMethodStatement, SingleLibraryInterFaceMethodStatement, SingleLibraryBusinessMethodStatement, RelationalOperator) имеют определенный интерфейс или супертип, вы можете использовать его с существующим filter() method:

for (ifStatement : ifElseStatement.eAllContents.toIterable.filter(IfStatements)){
    for (statement : ifStatement.expression.eAllContents.toIterable.filter(Statement)) {
            expressionDemand += getDemand(statement,resourceTable)                          
    }
}
def Demand getDemand(Statement statement, ResourceTable resourceTable){
    ...
}

Другое решение состоит в том, чтобы избежать в этом случае filter и использовать switch с такими охранниками типа:

for (ifStatement : ifElseStatement.eAllContents.toIterable.filter(IfStatements)){
    for (it : ifStatement.expression.eAllContents) {
        switch(it){
            SingleLibraryPersistenceMethodStatement,
            SingleLibraryPersistenceMethodStatement,
            SingleLibraryBusinessMethodStatement:
                 expressionDemand += getDemand(it,resourceTable)
        }
    }
}
...