xtext - 在 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)
}
}
解决方案
<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)
}
}
}
推荐阅读
- java - 读取新终端窗口的控制台输出
- c# - 如何创建启动和停止多个“exe”/“bat”的 Windows 服务
- php - 拆分一个相当复杂的字符串,需要帮助
- sql - 从 XML 中选择所有匹配的字符串值
- sql-server - 如何在 SQL PDW/Azure SQL DW 中连接具有相同 ID 的多行
- java - android上的FileDownloader它没有显示错误,但下载没有开始
- sql-server - 如何将1列中的多列存储为sql中的值
- php - 将用户角色作为自定义元数据添加到 WooCommerce 订单
- node.js - Deprecation Warning Error with Blockchain
- html - 需要使用 Html.Action 传递参数和 csslink