Groovy gotchas

Рубрика: Groovy | 6 May 2008, 10:44 | juriy

Есть в англоязычном айтишном мире такое выражение “gotcha”: этим понятием обозначают поведение, неожиданное для пользователя. В русском языке есть куда более родное слово, которое намного точнее описывает суть: грабли.

Вот пара маленьких грабель языка Groovy, которые я обнаружил за вчерашний вечер.

1. Сравнение и эквивалентность.
В тех книгах, которые я успел прочесть указывается: “Groovy maps the == operator to the equals( ) method in Java.” Наш ответ: вот такой вот код:

[java]

class Gotcha implements Comparable {

	int field;
	int value;

	public int compareTo(Gotcha o) {
		println "Compare called"
		return o.value - value;
	}

	public int hashCode() {
		return field*100;
	}

	public boolean equals(Object obj) {
		println "Equals called"
		return field == obj.field
	}

	static void main(String[] args) {
		Gotcha g1 = new Gotcha(field:1, value:10);
		Gotcha g2 = new Gotcha(field:1, value:15);

		assert g1.equals(g2)
		assert g1 != g2
	}

[/java]

Очевидно, когда класс реализует comparable, вызывается не eqals, а compare. На мой взгляд это, некорректно.

Как оказалось, на эту “особенность” заведен отдельный баг

2. Размер списка:
[java]

def list = [
	[1, 2]
	[1, 2]
	[1, 2]
]

assert list.size() == 1

[/java]

Проблема в том, что я забыл разделить элементы списка запятыми. Странно, что груви позволил запустить такой код и, фактически, создал список:

[java]

println list

>> [[null, null]]

[/java]

Комментариев: 6

6 Responses to “Groovy gotchas”

Комментарии:

  1. Serger

    В общем что-то так поэксперементировал с ruby:
    a=[[1,2][1,2][1,2]]
    =>[[]]
    a[1]
    =>nil

    a[0]
    =>[]
    a[0][0]
    =>nil
    a[0][1]
    =>nil

  2. Serger

    a.size
    =>1

  3. Kefir

    Вааче-то для равных, с точки зрения equals, объектов compareTo должен выдавать 0. И, например, TreeSet и TreeMap вообще не вызывают equals.

    Так что не вижу здесь ничего фатального, просто нужно следовать правилам, вот и все.

  4. Juriy

    Вообще-говоря, замечание почти правильное.

    >> It is strongly recommended (though not required) that natural orderings be consistent with equals.

    Но строго, compareTo определяет _последовательность_ элементов, а не их равенство/неравенство. Так, при сортировке используется compareTo, а при получении значения – equals и hashCode. Фатального, естественно, ничего нет (до тех пор, пока на Groovy не начнут писать системы жизнеобеспечения).

    >> И, например, TreeSet и TreeMap вообще не вызывают equals.

    TreeMap вызывает equals.

  5. Kefir

    >> TreeMap вызывает equals.
    Точно, тогда и TreeSet тоже, т.к. TreeSet узает внутри TreeMap… Хм… Вроде в ранних версиях не вызывал, видимо это тоже посчитали багом. А может я гоню :)

  6. guai

    > Странно, что груви позволил запустить такой код и, фактически, создал список: [[null, null]]
    Первое [1, 2] создает список, второе берет его первый и второй элемент (считая с нулевого) тоже в виде списка [2, null], а третье – берет 1й и 2й элементы этого списка. Всё нормально :)

Leave a Reply