Class::Comparable - A base class for comparable objects
# an example subclass package Currency::USD; use base 'Class::Comparable'; sub new { my $class = shift; bless { value => shift }, $class; } sub value { (shift)->{value} } sub compare { my ($left, $right) = @_; # if we are comparing against another # currency object, then compare values if (ref($right) && $right->isa('Currency::USD')) { return $left->value <=> $right->value; } # otherwise assume we are comparing # against a numeric value of some kind else { return $left->value <=> $right; } } # an example usage of Class::Comparable object my $buck_fifty = Currency::USD->new(1.50); my $dollar_n_half = Currenty::USD->new(1.50); ($buck_fifty == $dollar_n_half) # these are equal (1.75 > $buck_fifty) # 1.75 is more than a buck fifty my $two_bits = Currency::USD->new(0.25); ($two_bits < $dollar_n_half) # 2 bits is less than a dollar and a half ($two_bits == 0.25) # two bits is equal to 25 cents
This module provides two things. First, it provides a base set of methods and overloaded operators for implementing objects which can be compared for equality (== & !=) and magnitude (<, <=, <=>, => & >). Second, it serves as a marker interface for objects which can be compared much like Java's Comparable interface.
==
!=
<
<=
<=>
=>
>
This method is abstract, and will throw an exception unless it is properly overridden by the class which implements Class::Comparable. This method is expected to return 1 if the invocant is greater than $compare_to, 0 if they are equal to one another and -1 if the invocant is less than $compare_to.
$compare_to
NOTE: This method used to have a second argument ($is_reversed) which handled the odd cases where comparison arguments are reversed. This is now handled automatically, so you can simply compare your objects values in the order they are passed to compare, and this class will handle the details.
$is_reversed
compare
Returns true (1) if the invocant is equal to the $compare_to argument (as determined by compare) and return false (0) otherwise.
1
0
Returns true (1) if the invocant is not equal to the $compare_to argument (as determined by equals) and return false (0) otherwise.
equals
Returns true (1) if the invocant is greater than or equal to $left and less than or equal to $right (as determined by compare) and return false (0) otherwise. This method does not enforce the fact that $left should be less than $right so that it can allow for compare to accept non-standard values.
$left
$right
Returns true (1) if the invocant is exactly the same instance as $compare_to and return false (0) otherwise. This method will correctly handle objects who overload the "" (stringification) operator.
""
This operator is implemented by the equals method.
This operator is implemented by the notEquals method.
notEquals
This operator is implemented by the compare method. It should be noted that perl will auto-generate the means to handle the <, <=, >= and > operators as well (see the overload docs for more information about auto-generation).
The compare method now works correctly (and automatically) even if the values being compared are reversed. This usually only happens when an object is compared to another non-object (or another object which doesn't overload the <=> operator). For instance, if the object is the left operand, like this:
($obj < 5) # the $obj is less than 5
then the arguments to the compare routine will be in the correct order. However if the object is the right operand, like this:
(5 > $obj) # 5 is greater than $obj
then the arguments to the compare routine will be in the wrong order, meaning that our first argument is our right operand, and our second argument is our left operand. We take care of the details of reversing the output to make sure that the comparison returns the correct value.
None that I am aware of. Of course, if you find a bug, let me know, and I will be sure to fix it.
I use Devel::Cover to test the code coverage of my tests, below is the Devel::Cover report on this module test suite.
------------------------ ------ ------ ------ ------ ------ ------ ------ File stmt branch cond sub pod time total ------------------------ ------ ------ ------ ------ ------ ------ ------ Class/Comparable.pm 100.0 100.0 100.0 100.0 100.0 100.0 100.0 ------------------------ ------ ------ ------ ------ ------ ------ ------ Total 100.0 100.0 100.0 100.0 100.0 100.0 100.0 ------------------------ ------ ------ ------ ------ ------ ------ ------
There are a number of comparison modules out there (http://search.cpan.org/search?query=Compare&mode=all), many of which can be used in conjunction with this module to help implement the compare method for your class.
stevan little, <stevan@iinteractive.com>
Copyright 2004 by Infinity Interactive, Inc.
http://www.iinteractive.com
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
To install Class::Comparable, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Class::Comparable
CPAN shell
perl -MCPAN -e shell install Class::Comparable
For more information on module installation, please visit the detailed CPAN module installation guide.