Groovy сравнить для CustomClass и чисел / строк - PullRequest
0 голосов
/ 16 декабря 2018

Я создаю DSL и пытаюсь определить пользовательский класс CustomClass, который вы можете использовать в выражениях типа

def result = customInstance >= 100 ? 'a' : 'b'
if (customInstance == 'hello') {...}

Groovy не вызывает ==, когда ваш класс определяет equals и реализуетComparable (определяет compareTo) одновременно.

Вместо этого Groovy вызывает compareToWithEqualityCheck, у которого есть логика ветвления.И если ваш пользовательский класс DSL не может быть назначен из String или Number, ваш пользовательский compareTo не будет вызываться для приведенного выше примера.

Вы не можете расширить CustomClass с помощью String.Я чувствую, что что-то упустил.Надеюсь, вы поможете мне понять, как реализовать простой случай, как я показал выше.

1 Ответ

0 голосов
/ 24 декабря 2018

Вот краткий ответ: вы можете продлить GString для CustomClass.Затем его метод compareTo будет вызываться в обоих случаях - когда вы проверяете равенство и когда вы фактически сравниваете.

Редактировать: Рассматривая следующие случаи, он будет работать для 1 и 2, но не для 3.

customInstance >= 100      // case 1
customInstance == 'hallo'  // case 2
customInstance == 10       // case 3

Теперь я объясню, что я понимаю из реализации в Groovy ScriptBytecodeAdapter и DefaultTypeTransformation.

Для оператора ==, в случае реализации Comparable (и тамне простая идентификация), он пытается использовать интерфейсный метод CompareTo, следовательно, ту же логику, которая используется для других операторов сравнения.Только если Comparable не реализован, он пытается определить равенство, основываясь на некоторых корректных умных типах, и, поскольку отношение ultima возвращается к вызову метода equals.Это происходит в DefaultTypeTransformation.compareEqual # L603-L608

Для всех других операторов сравнения, таких как >=, Groovy делегирует метод compareToWithEqualityCheck.Теперь этот метод вызывается с флагом equalityCheckOnly, установленным в значение false, в то время как для него устанавливается значение true для первого случая, когда вызов происходит из оператора ==.Опять же, есть некоторая умность Groovy, основанная на типе левой стороны, если это Number, Character или String.Если ни один из них не применяется, он вызывает метод CompareTo в DefaultTypeTransformation.compareToWithEqualityCheck # L584-L586 .

Теперь это происходит только в том случае, если

!equalityCheckOnly || left.getClass().isAssignableFrom(right.getClass())
  || (right.getClass() != Object.class && right.getClass().isAssignableFrom(left.getClass())) //GROOVY-4046
  || (left instanceof GString && right instanceof String)

Существуют некоторые ограничениядля случая equalityCheckOnly, следовательно, когда мы пришли от оператора ==.Хотя я не могу объяснить все те, которые, по моему мнению, должны предотвращать возникновение исключений при определенных обстоятельствах, таких как проблема, упомянутая в комментарии.

Для краткости я не упомянул выше, что существуют также случаи, которые обрабатываютсяв ScriptBytecodeAdapter и делегирован equals сразу, если левая и правая стороны имеют одинаковый тип и одно из целых, двойных или длинных.

...