首页 > 解决方案 > 在 Xtend 中的 Iterable 对象的过滤函数中传递多种类型作为参数

问题描述

我正在使用 Xtext 的 DSL 生成器接口,以便基于我的 Xtext DSL 生成一些模型。这工作正常,但现在我在编写生成器时遇到了一些问题。我正在使用生成器过滤掉在我的 Xtext DSL 中声明的规则。我通过选择某些规则然后将它们转换为一个Iterable对象来做到这一点,然后我可以使用它来过滤某些类型(请参阅toIterable.filter()下面我的代码中的部分)。下面的代码包含一个 for 循环,它本身又包含 3 个嵌套的 for 循环。这些嵌套循环都过滤一种特定类型的方法语句(我在 DSL 中声明的类型)。我想通过将 3 种类型作为参数传递给filter()方法。在这种情况下,会有一个嵌套的 for 循环,其中条件理想情况下看起来像:

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

问题是该filter()方法只接受一个参数(一种类型),所以现在我必须编写三个调用的调度方法getDemand,它们基本上都做同样的事情。它现在可以工作,但这迫使我为要过滤的每种类型编写大量样板代码。

有没有一种方法可以在不创建大量样板代码的情况下过滤多种类型(在一个 for 循环中)?

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)                            
        }
}

标签: xtextiterablextend

解决方案


<T> T filter(Class<T>)不能做多种类型,因为返回类型不能是T但是 - 在极端情况下Object必须稍后强制转换。

但是:如果您的四种类型(SingleLibraryPersistenceMethodStatement, SingleLibraryInterFaceMethodStatement, SingleLibraryBusinessMethodStatement, RelationalOperator)共享一个特定的接口或超类型,您可以将其与现有filter()方法一起使用:

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)
        }
    }
}

推荐阅读