简体   繁体   English

在 Xtend 中的 Iterable object 的过滤器 function 中将多种类型作为参数传递

[英]Pass multiple types as parameter in filter function of Iterable object in Xtend

I am using the DSL generator interface of Xtext in order to generate some models based on my Xtext DSL.我正在使用 Xtext 的 DSL 生成器接口,以便基于我的 Xtext DSL 生成一些模型。 This is working fine, but right now I am facing a bit of a problem in writing the generator.这工作正常,但现在我在编写生成器时遇到了一些问题。 I am using the generator to filter out Rules declared in my Xtext DSL.我正在使用生成器过滤掉在我的 Xtext DSL 中声明的规则。 I do this by selecting certain Rules and then convert them in an Iterable object, which I can then use to filter on certain types (see the toIterable.filter() parts in my code below).为此,我选择某些规则,然后将它们转换为Iterable object,然后我可以使用它来过滤某些类型(请参阅下面我的代码中的toIterable.filter()部分)。 The code below contains one for loop which itself again contains 3 nested for loops.下面的代码包含一个 for 循环,它本身又包含 3 个嵌套的 for 循环。 These nested loops all filter on one specific kind of Method Statement (types that I declared in my DSL).这些嵌套循环都过滤一种特定类型的方法语句(我在 DSL 中声明的类型)。 I would like to combine these 3 for loops in one for loop by passing the 3 types as parameters in the filter() method.我想通过将 3 种类型作为参数传递给filter()方法,将这 3 个 for 循环组合成一个 for 循环。 In this case there would be one nested for loop where the condition would ideally look something like:在这种情况下,会有一个嵌套的 for 循环,其中条件理想情况下看起来像:

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

The problem is that the filter() method only takes one argument (one type), so right now I have to write three dispatch methods called getDemand which all basically do the same.问题是filter()方法只接受一个参数(一种类型),所以现在我必须编写三个名为getDemand的调度方法,它们基本上都做同样的事情。 It works right now, but this forces me to write a lot of boilerplate code for each type that I want to filter.它现在可以工作,但这迫使我为要过滤的每种类型编写大量样板代码。

Is there a way to filter multiple types (in one for loop) without creating a lot of boilerplate code?有没有一种方法可以在不创建大量样板代码的情况下过滤多种类型(在一个 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)                            
        }
}

<T> T filter(Class<T>) cannot do multiple types because then the return type could not be T but - in the extreme case Object which must be cast later. <T> T filter(Class<T>)不能做多种类型,因为返回类型不能是T但 - 在极端情况下Object必须稍后强制转换。

But: If your four types ( SingleLibraryPersistenceMethodStatement , SingleLibraryInterFaceMethodStatement , SingleLibraryBusinessMethodStatement , RelationalOperator ) share a specific interface or supertype you can used that with the existing filter() method:但是:如果您的四种类型( SingleLibraryPersistenceMethodStatementSingleLibraryInterFaceMethodStatementSingleLibraryBusinessMethodStatementRelationalOperator )共享特定的接口或超类型,则可以将其与现有的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){
    ...
}

Another solution is to avoid filter in this case and use switch with type guards like this:另一种解决方案是在这种情况下避免filter并使用带有类型保护的switch ,如下所示:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM