NAME
Class::Comparable - A base class for comparable objects
SYNOPSIS
# 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
DESCRIPTION
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.
METHODS
- compare ($compare_to)
-
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
.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 tocompare
, and this class will handle the details. - equals ($compare_to)
-
Returns true (
1
) if the invocant is equal to the$compare_to
argument (as determined bycompare
) and return false (0
) otherwise. - notEquals ($compare_to)
-
Returns true (
1
) if the invocant is not equal to the$compare_to
argument (as determined byequals
) and return false (0
) otherwise. - isBetween ($left, $right)
-
Returns true (
1
) if the invocant is greater than or equal to$left
and less than or equal to$right
(as determined bycompare
) and return false (0
) otherwise. This method does not enforce the fact that$left
should be less than$right
so that it can allow forcompare
to accept non-standard values. - isExactly ($compare_to)
-
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.
OPERATORS
- ==
-
This operator is implemented by the
equals
method. - !=
-
This operator is implemented by the
notEquals
method. - <=>
-
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).
IMPORTANT NOTE
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.
BUGS
None that I am aware of. Of course, if you find a bug, let me know, and I will be sure to fix it.
CODE COVERAGE
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
------------------------ ------ ------ ------ ------ ------ ------ ------
SEE ALSO
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.
AUTHOR
stevan little, <stevan@iinteractive.com>
COPYRIGHT AND LICENSE
Copyright 2004 by Infinity Interactive, Inc.
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.