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 to compare, 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 by compare) and return false (0) otherwise.

notEquals ($compare_to)

Returns true (1) if the invocant is not equal to the $compare_to argument (as determined by equals) 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 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.

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.

http://www.iinteractive.com

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.