Signature of Matchers.greaterThan etc

36 views
Skip to first unread message

Duncan McGregor

unread,
Nov 1, 2011, 2:08:18 PM11/1/11
to Hamcrest Java Users
I know that generics must be the bane of your lives as well, but can I
have an issue where I can't pass a joda.DateTime to
Matchers.greaterThan etc

My problem goes away if the signature of the methods is changed from

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

to

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

Some discussion here

http://stackoverflow.com/questions/7970163/generics-hell-how-do-i-pass-a-joda-datetime-to-hamcrest-matcher-greaterthan

and here

http://stackoverflow.com/questions/6452313/how-to-implement-a-generic-maxcomparable-a-comparable-b-function-in-java

Cheers

Duncan

Nat Pryce

unread,
Nov 1, 2011, 5:07:00 PM11/1/11
to hamcre...@googlegroups.com
Aaaagghhhh kill me now. Fucking java generics.

www.natpryce.com

> --
> You received this message because you are subscribed to the Google Groups "Hamcrest Java Users" group.
> To post to this group, send email to hamcre...@googlegroups.com.
> To unsubscribe from this group, send email to hamcrest-jav...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/hamcrest-java?hl=en.
>

Nat Pryce

unread,
Nov 1, 2011, 5:07:22 PM11/1/11
to hamcre...@googlegroups.com
Ok ok I'll have a look when I get the time

www.natpryce.com

On 1 Nov 2011, at 18:08, Duncan McGregor <oneey...@googlemail.com> wrote:

Nat Pryce

unread,
Nov 1, 2011, 5:07:39 PM11/1/11
to hamcre...@googlegroups.com
Or do you want commit access?

www.natpryce.com

On 1 Nov 2011, at 18:08, Duncan McGregor <oneey...@googlemail.com> wrote:

Duncan McGregor

unread,
Nov 1, 2011, 6:32:11 PM11/1/11
to Hamcrest Java Users
On 1 November 2011 21:07, Nat Pryce <nat....@gmail.com> wrote:
Or do you want commit access?

After seeing the state of those who have - nice try ;-)

The following patch though passes the current tests and leads to
Matchers with what I believe is the correct signature. But frankly I'm
a little out of my depth when it comes to this level of generics -
it's only because Jon Skeet validated it that I dared even suggest the
change!

D

$ svn diff hamcrest-library/src/main/java/org/hamcrest/number/
OrderingComparison.java
Index: hamcrest-library/src/main/java/org/hamcrest/number/
OrderingComparison.java
===================================================================
--- hamcrest-library/src/main/java/org/hamcrest/number/
OrderingComparison.java (revision 727)
+++ hamcrest-library/src/main/java/org/hamcrest/number/
OrderingComparison.java (working copy)
@@ -7,7 +7,7 @@
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;

-public class OrderingComparison<T extends Comparable<T>> extends
TypeSafeMatcher<T> {
+public class OrderingComparison<T extends Comparable<? super T>>
extends TypeSafeMatcher<T> {
private static final int LESS_THAN = -1;
private static final int GREATER_THAN = 1;
private static final int EQUAL = 0;
@@ -55,7 +55,7 @@
* @return Is value = expected?
*/
@Factory
- public static <T extends Comparable<T>> Matcher<T>
comparesEqualTo(T value) {
+ public static <T extends Comparable<? super T>> Matcher<T>
comparesEqualTo(T value) {
return new OrderingComparison<T>(value, EQUAL, EQUAL);
}

@@ -63,7 +63,7 @@
* Is value > expected?
*/
@Factory
- public static <T extends Comparable<T>> Matcher<T> greaterThan(T
value) {
+ public static <T extends Comparable<? super T>> Matcher<T>
greaterThan(T value) {
return new OrderingComparison<T>(value, GREATER_THAN,
GREATER_THAN);
}

@@ -71,7 +71,7 @@
* Is value >= expected?
*/
@Factory
- public static <T extends Comparable<T>> Matcher<T>
greaterThanOrEqualTo(T value) {
+ public static <T extends Comparable<? super T>> Matcher<T>
greaterThanOrEqualTo(T value) {
return new OrderingComparison<T>(value, EQUAL, GREATER_THAN);
}

@@ -79,7 +79,7 @@
* Is value < expected?
*/
@Factory
- public static <T extends Comparable<T>> Matcher<T> lessThan(T
value) {
+ public static <T extends Comparable<? super T>> Matcher<T>
lessThan(T value) {
return new OrderingComparison<T>(value, LESS_THAN,
LESS_THAN);
}

@@ -87,7 +87,7 @@
* Is value <= expected?
*/
@Factory
- public static <T extends Comparable<T>> Matcher<T>
lessThanOrEqualTo(T value) {
+ public static <T extends Comparable<? super T>> Matcher<T>
lessThanOrEqualTo(T value) {
return new OrderingComparison<T>(value, LESS_THAN, EQUAL);
}
}

Steve Freeman

unread,
Nov 1, 2011, 8:06:12 PM11/1/11
to hamcre...@googlegroups.com
I lost a year of my life to struggling with the interaction of hamcrest and jmock generics which I'll never get back. We can try your proposal but a test case would be nice too;)

S.

Steve Freeman
http://www.higherorderlogic.com

Written on a phone, so please allow for typos and short content.

On 1 Nov 2011, at 18:08, Duncan McGregor <oneey...@googlemail.com> wrote:

Duncan McGregor

unread,
Nov 1, 2011, 8:43:44 PM11/1/11
to Hamcrest Java Users
On Nov 2, 12:06 am, Steve Freeman <st...@m3p.co.uk> wrote:
> I lost a year of my life to struggling with the interaction of hamcrest and jmock generics which I'll never get back. We can try your proposal but a test case would be nice too;)

That's why I hesitated to submit a patch! Both the loss of a year, and
the thought of a test-case.

I can create a test which fails to compile before the patch is applied
and succeeds after, albeit only by defining 2 implementations of
Comparable. And I suppose that will show that the signature is on-
purpose. What it won't show is that the change doesn't break thousands
of lines of client code...

D

Steve Freeman

unread,
Nov 2, 2011, 4:25:52 PM11/2/11
to hamcre...@googlegroups.com
On 2 Nov 2011, at 00:43, Duncan McGregor wrote:
> I can create a test which fails to compile before the patch is applied
> and succeeds after, albeit only by defining 2 implementations of
> Comparable. And I suppose that will show that the signature is on-
> purpose. What it won't show is that the change doesn't break thousands
> of lines of client code...

You could submit an example of the code that you want to compile.

This is one of the reasons we've been stuck with the new release. We haven't been able to get enough people to confirm that the latest version doesn't break the world.

S.

Steve Freeman

Winner of the Agile Alliance Gordon Pask award 2006
Book: http://www.growing-object-oriented-software.com

+44 797 179 4105
Twitter: @sf105
Higher Order Logic Limited
Registered office. 2 Church Street, Burnham, Bucks, SL1 7HZ.
Company registered in England & Wales. Number 7522677

Duncan McGregor

unread,
Nov 3, 2011, 2:12:53 PM11/3/11
to Hamcrest Java Users
On Nov 2, 8:25 pm, Steve Freeman <st...@m3p.co.uk> wrote:

> You could submit an example of the code that you want to compile.

I did on StackOverflow. But a test case is better - here is one using
local classes rather than joda.DateTime

public void testComparisonsAllowSubclasses() {
assertThat(new MyComparable(11), greaterThan(new
MyComparable(10)));
assertThat(new SubComparable(11), greaterThan(new
SubComparable(10))); // doesn't compile without the patch
}

private static class MyComparable implements
Comparable<MyComparable> {
private int value;

public MyComparable(int value) {
this.value = value;
}

@Override public int compareTo(MyComparable o) {
return value - o.value;
}
}

private static class SubComparable extends MyComparable {

public SubComparable(int value) {
super(value);
}

}

> This is one of the reasons we've been stuck with the new release. We haven't been able to get enough people to confirm that the latest version doesn't break the world.

I feel your pain. I suppose you could just increment the version
number by so much that everyone will accept breaking changes ;-?

D

Rick Mugridge

unread,
Nov 3, 2011, 3:47:54 PM11/3/11
to hamcre...@googlegroups.com
hamcrest-all-1.3.0RC2.jar has been working fine for me, with no problem moving over to it. How do you get sufficient confirmations?

Duncan's proposed change makes sense, so that the type argument becomes covariant, which is appropriate in this case. Without covariance, it's necessary to cast a subtype (eg, None) to the type (eg, Option[T]) to get it through the Scala compiler.

Cheers, Rick


D

Duncan McGregor

unread,
Nov 4, 2011, 7:44:58 PM11/4/11
to Hamcrest Java Users
FWIW it was the difficulty in casting my out of this hole in Scala
that made me question the signature. Java lets you cast to the raw
Comparable, but Scala won't.

On Nov 3, 7:47 pm, Rick Mugridge <rick.mugri...@gmail.com> wrote:
> hamcrest-all-1.3.0RC2.jar has been working fine for me, with no problem
> moving over to it. How do you get *sufficient* confirmations?
>
> Duncan's proposed change makes sense, so that the type argument becomes
> covariant, which is appropriate in this case. Without covariance, it's
> necessary to cast a subtype (eg, None) to the type (eg, Option[T]) to get
> it through the Scala compiler.
>
> Cheers, Rick
>
> On Fri, Nov 4, 2011 at 7:12 AM, Duncan McGregor
> <oneeyed...@googlemail.com>wrote:

Steve Freeman

unread,
Nov 5, 2011, 7:05:55 AM11/5/11
to hamcre...@googlegroups.com
That might be out of scope...
Reply all
Reply to author
Forward
0 new messages