我正在尝试在Groovy中使用Java库,但是Groovy正在使用其自己的方法覆盖方法名称join
之一。
以下代码失败:
%%classpath add mvn
tech.tablesaw tablesaw-core 0.32.6
tech.tablesaw tablesaw-beakerx 0.32.6
com.jimmoores quandl-tablesaw 2.0.0
%import com.jimmoores.quandl.*
%import com.jimmoores.quandl.tablesaw.*
%import tech.tablesaw.api.*
// display Tablesaw tables with BeakerX table display widget
tech.tablesaw.beakerx.TablesawDisplayer.register()
TableSawQuandlSession session = TableSawQuandlSession.create();
Table table1 = session.getDataSet(DataSetRequest.Builder.of("FRED/BCNSDODNS").build());
table1.column("Value").setName("Corporate Credit");
Table table2 = session.getDataSet(DataSetRequest.Builder.of("FRED/CMDEBT").build());
table2.column("Value").setName("Household Credit");
Table result = table1.join("Date").inner(table2, "Date");
错误是:
groovy.lang.MissingMethodException:没有方法签名:java.lang.String.inner()适用于参数类型:(tech.tablesaw.api.Table,java.lang.String)
这很奇怪,Table.join(String)
返回一个DataFrameJoiner
:https://static.javadoc.io/tech.tablesaw/tablesaw-core/0.32.6/tech/tablesaw/api/Table.html#join-java.lang.String...-
我认为正在发生的事情是Table
是一个Iterable<Row>
,所以Groovy可能正在使用its own join method。
让我真正感到奇怪的是,即使我将Table
also implements Iterable<Row>
in that version的Tablesaw版本从0.32.6
切换到0.24.9
,它仍然有效
有什么想法可以迫使Groovy使用Tablesaw库中的join
方法而不是它自己的join
方法吗?
答案 0 :(得分:1)
根据其他答案,可以通过在方法调用中使用显式键入来解决此特殊情况。这里只是一些有关GroovyDefaultMethod重写的一般主题的背景信息。
关于此的文档很少。一些旧的电子邮件线程与来自DefaultGroovyMethods的这些方法有关:
how do methods in DefaultGroovyMethods get applied?
因此,当我们创建ArrayList元类时,我们检查 ArrayList类,从中获取所有方法,并制作我们的元方法 出来。然后,我们获得DGM方法列表,并在中应用所有方法 他们的依赖于继承 ...”
这也许可以解释为什么根据Iterable
的确切继承详细信息,使用不同的Tablesaw版本会得到不同的结果。
如果要在脚本执行期间执行此操作,可以使用 每个实例的metaClass要做的事情:
this.metaClass.println = { Object value -> System.out.println "woo $value" }
据此,我相信您可以修改Table
的元类以使用您要使用的方法。由于DefaultGroovyMethods的应用还取决于继承细节,因此您也可以尝试对Table进行子类化。
metaprogramming docs也可能有帮助。
答案 1 :(得分:1)
您遇到了这个问题,因为Table.join()
方法的原型如下:
public DataFrameJoiner join(String... columnNames)
您已经注意到Groovy通过其Iterable<T>
方法增强了join()
类,但是其原型如下:
public String join(String separator)
来源:http://docs.groovy-lang.org/latest/html/groovy-jdk/java/lang/Iterable.html#join(java.lang.String)
这就是以下情况的原因:
table1.join("Date").inner(table2, "Date");
Groovy解析Iterable<T>.join(String separator)
而不是Table
类中的方法。它仅与0.24.9版本配合使用,因为它提供了具有以下原型的方法:
public DataFrameJoiner join(String columnName)
因此,在这种情况下,Table.join(String columnName)
覆盖了方法Iterable<T>.join(String separator)
。
您可以通过使用显式的String[]
参数信息进行调用来解决此问题,因此Groovy会立即选择正确的方法。
table1.join(["Date"] as String[]).inner(table2, "Date")
如果您传递两个字符串以使Groovy选择varargs方法,那么它将没有任何明确的参数类型信息就可以工作。
table1.join("Date", "Something").inner(table2, "Date")
但是,对于单个字符串参数,由于有两种重载方法定义,因此您需要进行显式的参数选择。