Search code examples
javaarraysinterfacecomparestring-comparison

Inapplicable method error regarding interfaces


I'm having an issue with one of my methods findLargest(Comparable[ ] arr) in class FindLargest that's meant to return the largest element in an array.

Apparently, in class Lab5Main this method works fine with fractions, but I get a compilation error with dates. In the system print out command, I'm getting this error:

The method findLargest(Comparable[ ]) in the type FindLargest is not applicable for the arguments (MyDate[ ])

Here is the supposed program output:

The largest fraction is 9/4
The latest date is 18/8/2011

My codes are shown below:

public class Lab5Main {

  public static void main(String[] args) {

    // Fraction
    Fraction fractions[] = new Fraction[3];
    fractions[0] = new Fraction(1, 2);
    fractions[1] = new Fraction(6, 11);
    fractions[2] = new Fraction(9, 4);
    System.out.println("The largest fraction is " + FindLargest.findLargest(fractions));

    // MyDate
    MyDate dates[] = new MyDate[3];
    dates[0] = new MyDate(1898, 6, 9);
    dates[1] = new MyDate(2003, 4, 1);
    dates[2] = new MyDate(2011, 8, 18);
    System.out.println("The latest date is " + FindLargest.findLargest(dates));

  }
}
public class FindLargest {
    public static <T extends Comparable<? super T>> T findLargest(T[] arr) {
        if (arr.length == 0) {
            return null;
        }
        T max = arr[0];
        for (int i = 0; i < arr.length; i++) {
            if (arr[i].compareTo(max) > 0) {
                max = arr[i];
            }
        }
        return max;
    }
public class Fraction implements Comparable<Fraction> { 
    private int num, denom;

public int gcd(int a, int b)  {  
        if (a%b==0) {
            return b;
        }
        return gcd(b, a%b);  
    } 

    public void reduce()  {  
        int g = gcd(num, denom);  

        num = num / g;  
        denom = denom / g;  
    }  

    public Fraction(int n, int d) {

        if (n==0) {
            d=1;
        }
        if (d==0) {
            n=1;
            d=2;
        }
        if(d<0) {
            n=-n;
            d=-d;
        }

        num = n;
        denom = d;

        reduce();
    }

    public String toString() {
        return num + "/" + denom;
    }

@Override
      public int compareTo(Fraction f) {
//        Fraction f = (Fraction) obj;
          if (Math.abs(value() - f.value()) < 0.00001) {
              return 0;
          }
          if (value() > f.value()) {
              return 1;
          }
          return -1;
      }
      public int compareTo(Object obj) {
          Fraction f = (Fraction) obj;
          if (Math.abs(value() - f.value()) < 0.00001) {
              return 0;
          }
          if (value() > f.value()) {
              return 1;
          }
          return -1;
      }

}

public class MyDate implements Comparable<MyDate> {
  private int year, month, day;

public MyDate(int z, int y, int x) {
      if (z<1000 || z>3000) {
          z = 2000;
      }
      if (y<1 || y>12) {
          y = 1;
      }
      if (x<1 || x>31) {
          x = 1;
      }

      day = x;
      month = y;
      year = z;
  }

  public String toString() {
        return day + "/" + month + "/" + year;
    }

  @Override
  public int compareTo (MyDate date){
//    MyDate date = (MyDate) obj;
      int diffYear = year - date.year;
      if (diffYear < 0) {
          return -1;
      }
      else if (diffYear > 0) {
          return 1;
      }

      int diffMonth = month - date.month;
      if (diffMonth < 0) {
          return -1;
      }
      else if (diffMonth > 0) {
          return 1;
      }

      int diffDay = day - date.day;
      if (diffDay < 0) {
          return -1;
      }
      else if (diffDay > 0) {
          return 1;
      }

      return 0;
  }
}

Solution

  • The issue is one of raw-types and generics. Comparable is a generic interface, but you are implementing it with a raw-type and you are using it with raw-types. You should fix that. Something like,

    public static <T extends Comparable<? super T>> T findLargest(T[] arr) {
        if (arr.length == 0) {
            return null;
        }
        T max = arr[0];
        for (int i = 0; i < arr.length; i++) {
            if (arr[i].compareTo(max) > 0) {
                max = arr[i];
            }
        }
        return max;
    }
    

    will ensure that you call findLargest with a generic type T that can be compared with itself and all of its' superclasses. You should also change Fraction and MyDate. Something like,

    public class Fraction implements Comparable<Fraction> { 
        // ...
        @Override
        public int compareTo(Fraction f) {
            if (Math.abs(value() - f.value()) < 0.00001) {
                return 0;
            }
            if (value() > f.value()) {
                return 1;
            }
            return -1;
        }
    }
    

    And MyDate similarly. I would recommend you always use the @Override annotation when you intend to override a method.