Предотвратить GroovyDefaultMethods join () от теневого метода join () класса Java? - PullRequest
1 голос
/ 01 июня 2019

Я пытаюсь использовать библиотеку Java в Groovy, но 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 подхватывает свой собственный метод соединения .

Что действительно странно, так это то, что он работает, если я переключаю версию Tablesaw с 0.32.6 на 0.24.9, хотя Table также реализует Iterable<Row> в этой версии

Есть идеи, как заставить Groovy использовать метод join из библиотеки Tablesaw вместо собственного join метода?

Ответы [ 2 ]

1 голос
/ 01 июня 2019

Вы столкнулись с этой проблемой, потому что прототип метода Table.join() выглядит следующим образом:

public DataFrameJoiner join(String... columnNames)

Источник: https://static.javadoc.io/tech.tablesaw/tablesaw-core/0.32.6/tech/tablesaw/api/Table.html#join-java.lang.String...-

Вы уже заметили, что 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)

Источник: https://static.javadoc.io/tech.tablesaw/tablesaw-core/0.24.9/tech/tablesaw/api/Table.html#join-java.lang.String-

Так что в этом случае 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")

Однако в случаеоднострочный аргумент, вам нужно сделать явный выбор параметра из-за определения двух методов перегрузки.

1 голос
/ 01 июня 2019

Как и в другом ответе, этот особый случай может быть решен с помощью явной типизации в вызове метода. Вот лишь дополнительная справочная информация по общей теме переопределения GroovyDefaultMethod.

Документация по этому вопросу недостаточна. Некоторые старые темы электронной почты относятся к этим методам из DefaultGroovyMethods :

  • как применяются методы в DefaultGroovyMethods?

    поэтому, когда мы создаем мета-класс ArrayList, мы проверяем Класс ArrayList, возьмите все методы из него и сделайте наши мета методы из этого. Затем мы получаем список методов DGM и применяем все методы в их в зависимости от наследства ... "

    Это может объяснить, почему вы получаете разные результаты с разными версиями Tablesaw, в зависимости от точных деталей наследования от Iterable.

  • Переопределить метод из DefaultGroovyMethods

    Если вы хотите сделать это во время действия сценария, вы можете использовать метакласс для каждого экземпляра:

     this.metaClass.println = { Object value ->
          System.out.println "woo $value"
     }
    

Исходя из этого, я считаю, что вы можете изменить метакласс Table, чтобы использовать метод, который вы хотите использовать. Поскольку применение DefaultGroovyMethods также зависит от деталей наследования, вы также можете попробовать создать подклассы Table.

Также могут помочь документы метапрограммирования .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...