Generics Hell — как передать joda.DateTime в Hamcrest Matcher.greaterThan?

JodaTime имеет

public final class DateTime extends BaseDateTime {...}

который работает до

public interface ReadableInstant extends Comparable<ReadableInstant>

Хэмкрест имеет

public static <T extends java.lang.Comparable<T>> org.hamcrest.Matcher<? super T>
    greaterThan(T value) {...}

Если я попытаюсь

greaterThan(new DateTime());

затем я получаю ошибку компиляции (Eclipse дает больше всего подсказок)

Универсальный метод moreThan(T) типа Matchers неприменим для аргументов (DateTime). Выведенный тип DateTime не является допустимой заменой ограниченного параметра >

Я прав, думая, что подпись greaterThan на самом деле должна быть

public static <T extends java.lang.Comparable<? super T>> org.hamcrest.Matcher<? super T>     
    greaterThan(T value)

? И есть ли способ совместить их вместе, кроме приведения к необработанному Comparable?


person Duncan McGregor    schedule 01.11.2011    source источник
comment
См. также stackoverflow.com/questions/6452313/   -  person Duncan McGregor    schedule 01.11.2011
comment
текущий источник OrderingComparison содержит <T extends Comparable<T>> Matcher<T> greaterThan(T value).   -  person David Harkness    schedule 01.11.2011
comment
@DavidHarkness - я должен сказать, что смотрел на 1.3.0RC1, но разве RC2 не меняет только тип возвращаемого значения? Это аргумент, который не принимается.   -  person Duncan McGregor    schedule 01.11.2011
comment
Да, кажется, что последний код не будет работать с двумя разными подклассами одного родительского класса.   -  person David Harkness    schedule 01.11.2011


Ответы (2)


Да, мне кажется, что это была бы лучшая подпись.

Вы пытались указать тип сравнения явно?

Matchers.<ReadableInstant>greaterThan(new DateTime());

Я не верю, что вы можете вызвать его, используя статический импорт, а также указать аргумент типа, к сожалению, но это может быть не слишком сложно.

Конечно, альтернативой является приведение аргумента:

greaterThan((ReadableInstant) new DateTime());

У меня нет Hamcrest под рукой, но вышеизложенное отлично сработало для меня, используя подпись, которую вы мне дали, в тестовом типе.

person Jon Skeet    schedule 01.11.2011
comment
Я не знал, что вы можете «привести» метод — это открывает целый новый мир синтаксиса Java! - person Duncan McGregor; 01.11.2011
comment
@Duncan Вы не применяете метод. Вы указываете параметр типа метода, поэтому компилятору не нужно выводить его из типа аргумента. - person Christian Semrau; 02.12.2011
comment
На самом деле это Matchers, а не Matcher: (Matchers.‹ReadableInstant›greaterThan(DateTime.now()) - person Shawn Lauzon; 06.11.2012

Если вы часто используете его и вас беспокоит преобразование, вы также можете реализовать свой собственный Matcher следующим образом:

public static Matcher<AbstractPartial> isAfter(final AbstractPartial partial) {
    return new BaseMatcher<AbstractPartial>(){

        @Override
        public void describeTo(final Description description) {
            description.appendText("after partial: ").appendValue(partial);
        }

        @Override
        public boolean matches(final Object object) {
            if (object instanceof AbstractPartial) {
                return ((LocalDate) object).isAfter(partial);
            }
            return false;
        }
    };
}

И протестируйте это так:

    Set<LocalDate> dates = Sets.newHashSet(new LocalDate(2013, 1, 1), new LocalDate(2013, 1, 2), new LocalDate(
        2013, 1, 3));
    assertThat(
        CollectionUtils.isEqualCollection(filter(isAfter(new LocalDate(2013, 1, 1)), dates),
            Lists.newArrayList(new LocalDate(2013, 1, 2), new LocalDate(2013, 1, 3))), is(true));

Если вы хотите использовать DateTime вместо LocalDate, просто замените AbstractPartial на AbstractInstant в первом листинге.

person Gismo Ranas    schedule 13.12.2013