-
-
Notifications
You must be signed in to change notification settings - Fork 429
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix comparing QuantityType with inverted dimensions #4571
base: main
Are you sure you want to change the base?
Conversation
Signed-off-by: Mark Herwege <[email protected]>
Signed-off-by: Mark Herwege <[email protected]>
While this returns the correct sign when comparing values, this is still not ideal. The big issues is that you can have a < b and b < a at the same time. And there is no solution for that. That also means that whenever comparing QuantityTypes the order of the arguments becomes very important. a > b, therefore b < a is no longer true. |
I am uncomfortable with a > b holds true whilst b > a is also true. Perhaps we just don't do any inversions here, which would render the above anomaly impossible, right? Make it the caller's responsibility to do inversion if they wanted to. |
Yes exactly. I don't like it either, but at some point the comparison was made possible with inverted dimensions. It just doesn't work. By the way, could the whole discussion on the forum (https://community.openhab.org/t/colors-and-json-issue/161860/31) also be impacted by this? |
I don't think we really need this PR as in the other PRs we will always convert quantities to the same common target unit value before doing a compare. |
Except that the compare is the wrong way around. And the method is called all the time. It is very confusing to have a method that overrides a standard method with exactly the opposite behaviour. I am not adding anything here, I am just trying to fix a bug and providing a test to avoid it in the future. We can remove the method of course and that would make sure this confusing behaviour never gets called. |
Signed-off-by: Mark Herwege <[email protected]>
Signed-off-by: Mark Herwege <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
equals should still work though, and as it just delegates to (internal)CompareTo, it needs fixed if we’re no longer allowing invertible units with compareTo
I also think internalCompareTo only exists so that it can easily call itself for the invertible case, and without that reason we may want to collapse its implementation back into the main compareTo
Signed-off-by: Mark Herwege <[email protected]>
That's fixed now.
I thought so myself, but the signature is different ( |
@mherwege I must admit that I struggle with Java generics syntax. And I notice that the basicprofiles StateFilter classes produces an enormous amount of warnings about wrong casts (relating to |
You are not alone. This sometimes feels like black magic to me as well. In my understanding, the main issue is that the compiler does not know the real class of T, it is only known at runtime. So trying to cast something to class T will always generate a compiler warning. Using ? just indicates it can be any type, so as long as it doesn't need to be cast, it is fine. I also am not always able to escape all conversion warnings. I did find a way to do so in this case, collapsing the method, by making comparable work accross QuantityTypes. But I couldn't get rid of all warnings in the class and I gave up for now. |
Signed-off-by: Mark Herwege <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey, one of the Java topics I actually do understand fairly well!
QuantityType<?>
andQuantityType
are the same. The latter is kind of deprecated, and you should never use it.- @mherwege is correct, that at runtime the generic type is erased completely. That's why you can't do
instanceof QuantityType<SomeType>
, onlyinstanceof QuantityType<?>
. All generic checks are done at compile time. AQuantityType<SomeType>
is implicitly convertible toQuantityType<?>
(like passing an object to a method that takesQuantityType<?>
), but not the opposite (returningQuantityType<?>
cannot be assigned to aQuantityType<SomeType>
without an explicit cast). Note thatSomeType
might be a concrete type, or it might be a type parameter, likeT
. Either way, it's a type, possibly with indirection, but not a wildcard. - If you have
public SomeType<T> someMethod(SomeType<T> t)
, theT
s must stay the same. You can't return aSomeType<OtherType>
than what was passed in to the method, nor aSomeType<?>
(which you got from some method returning that, such asQuantityType.inverse()
). You could return aSomeType<U>
, but only as long asU
can be determined in some way by the compiler. This similarly applies in this PR that theT
from the class definition must be the same all the way through the class -implements Comparable<QuantityType<T>>
meanscompareTo
must have the signaturepublic int compareTo(QuantityType<T>)
. But when you callcompareTo(other.inverse())
,other.inverse()
returns aQuantityType<?>
which may not be compatible, and the compiler complains - it has no way to know that we're checking at runtime that the inverse unit is compatible, and thus that the result ofother.inverse()
will be aQuantityType<T>
. The change in interface in this PR means you can now passQuantityType<Mired>
to aQuantityType<Kelvin>.compareTo
method (and it will raise anIllegalArgumentException
). Interestingly... this means prior to this PR, even thoughinternalCompareTo
could handle inverse units, the signature ofcompareTo
wouldn't allow it (at least not without warnings?), and thus we're not actually breaking anything in this PR.compareTo
never worked.equals
did.
@ccutrer Thank your for your explanation. |
Yes, that seems reasonable. For some reason I was thinking |
Signed-off-by: Mark Herwege <[email protected]>
@ccutrer wow. Brilliant! Thank you! |
Comparing QuantityType with inverted units was opposite of what it should be.
Also included tests to verify.
See openhab/openhab-addons#18122 (comment)
@andrewfg @jimtng