Re: Generics puzzle with implements Comparable
On Wed, 21 May 2008, Roedy Green wrote:
On Wed, 21 May 2008 12:26:23 +0100, Tom Anderson
<twic@urchin.earth.li> wrote, quoted or indirectly quoted someone who
said :
Could you clarify what you want to do? Comparing two SalesTaxItems, fine.
Comparing two DatedSalesTaxItems, fine, i guess. What should happen when
you compare one of one with one of the other? Do you want a SalesTaxItem
to be comparable with a DatedSalesTaxItem? Do you want that to behave the
same as doing the same comparison the other way around?
My Comparator Comparables are for sorting collections of either pure
SalesTaxItem or pure DatedSalesTaxItem
I handled it by cloning the code. It is mostly the same except for
adding one field and changing the Comparable to pay attention to the
extra field.
Here is the code cloned.
Ideally it should be rewritten somehow with DatedSalesTaxItem extending
SalesTaxItem.
That's the thing. It can't be. A SalesTaxItem is Comparable<SalesTaxItem>.
If a DatedSalesTaxItem is a SalesTaxItem, then it is also
Comparable<SalesTaxItem>. Them's the rules.
My suggestion would be to forget about Comparable, and write two separate
classes, a Comparator<SalesTaxItem>, and a Comparator<DatedSalesTaxItem>,
to do the job. You have to use them explicitly, but it's typesafe, with no
ickiness.
A type-safe but icky solution would be to equip SalesTaxItem with a
private method String getDate(), hardcoded to return a string indicating
the beginning of time ("19700101"), then to write the comparison method
using the date, as in DatedSalesTaxItem. In DatedSalesTaxItem, you just
have to override the getDate method to return the actual date, and make it
public. You can then declare SalesTaxItem Comparable<SalesTaxItem>, and
all will be well, including in comparisons of mixed kinds of item.
tom
----------------------------------------------------------------------------------------
package com.mindprod.americantax;
import java.util.Comparator;
/**
* triple country, percent, city
*/
class SalesTaxItem implements Comparable<SalesTaxItem>
{
protected String city;
protected final String county;
protected final double percent;
// -------------------------- PUBLIC INSTANCE METHODS
--------------------------
/**
* constructor
*
* @param county county name
* @param percent tax rate percent including state tax
* @param city city, region of county
*/
public SalesTaxItem( String county, double percent, String city )
{
this.county = county.trim();
this.city = city.trim();
this.percent = percent;
}
public void clearCity()
{
this.city = "";
}
/**
* Compare two Pairs. Callback for natural order sort for
deduping. effectively returns a-b;
*
* @return +1, a>b, 0 a=b, -1 a<b, case insensitive
*/
public final int compareTo( SalesTaxItem o )
{
int diff = this.county.compareTo( o.county );
if ( diff != 0 )
{
return diff;
}
if ( this.percent > o.percent )
{
return 1;
}
if ( this.percent < o.percent )
{
return -1;
}
return this.city.compareTo( o.city );
}// end compareTo
public String getCity()
{
return city;
}
public String getCounty()
{
return county;
}
public String getCountyCity()
{
if ( city == null || city.length() == 0 )
{
return county;
}
else
{
return county + ", " + city;
}
}
public double getPercent()
{
return percent;
}
// -------------------------- INNER CLASSES
--------------------------
/**
* sort triples alphabetically
*/
static final class Alphabetically implements
Comparator<SalesTaxItem>
{
/**
* Compare two triples. sort alphabetically without tax rate
considered. effectively returns b-a;
*
* @return +1, b>a, 0 a=b, -1 b<a, case insensitive
*/
public final int compare( SalesTaxItem o1, SalesTaxItem o2 )
{
int diff = o1.county.compareTo( o2.county );
if ( diff != 0 )
{
return diff;
}
return o1.city.compareTo( o2.city );
}// end compare
}
}
--------------------------------------------------------------------------------------
package com.mindprod.americantax;
import java.util.Comparator;
/**
* country, percent, city, date. Can't extend SalesTaxItem because of
Comparable compatibility.
*/
class DatedSalesTaxItem implements Comparable<DatedSalesTaxItem>
{
private String city;
private final String county;
private final String yyyymmdd;// in form yyyymmdd
private final double percent;
// -------------------------- PUBLIC INSTANCE METHODS
--------------------------
/**
* constructor
*
* @param county county name
* @param percent tax rate percent including state tax
* @param city city, region of county
* @param yyyymmdd date tax came into effect
*/
public DatedSalesTaxItem( String county, double percent, String
city, String yyyymmdd )
{
this.county = county.trim();
this.city = city.trim();
this.percent = percent;
this.yyyymmdd = yyyymmdd;
}
public void clearCity()
{
this.city = "";
}
/**
* Compare two Pairs. Callback for natural order sort for
deduping. effectively returns a-b;
*
* @return +1, a>b, 0 a=b, -1 a<b, case insensitive
*/
public final int compareTo( DatedSalesTaxItem o )
{
int diff = this.county.compareTo( o.county );
if ( diff != 0 )
{
return diff;
}
diff = this.city.compareTo( o.city );
if ( diff != 0 )
{
return diff;
}
diff = this.yyyymmdd.compareTo( o.yyyymmdd );
if ( diff != 0 )
{
return -diff;
}
if ( this.percent > o.percent )
{
return 1;
}
if ( this.percent < o.percent )
{
return -1;
}
return 0;
}// end compareTo
public String getCity()
{
return city;
}
public String getYYYYMMDD()
{
return yyyymmdd;
}
public String getCounty()
{
return county;
}
public String getCountyCity()
{
if ( city == null || city.length() == 0 )
{
return county;
}
else
{
return county + ", " + city;
}
}
public double getPercent()
{
return percent;
}
// -------------------------- INNER CLASSES
--------------------------
/**
* sort triples alphabetically
*/
static final class Alphabetically implements
Comparator<DatedSalesTaxItem>
{
/**
* Compare two triples. sort alphabetically without tax rate
considered. effectively returns b-a;
*
* @return +1, b>a, 0 a=b, -1 b<a, case insensitive
*/
public final int compare( DatedSalesTaxItem o1,
DatedSalesTaxItem o2 )
{
int diff = o1.county.compareTo( o2.county );
if ( diff != 0 )
{
return diff;
}
return o1.city.compareTo( o2.city );
}// end compare
}
}
--
They didn't have any answers - they just wanted weed and entitlement.