Переопределение метода equals () для учета разнородных объектов - PullRequest
1 голос
/ 09 ноября 2011

Ниже выбран код из одного из 5 классов для этого назначения.

Каждый класс должен иметь метод equals (), который может сравнивать объект своего класса с объектом любого из всех 5 классов.

Моя стратегия заключается в преобразовании каждого значения объекта в двойное значение для большей точности.

Поскольку каждый класс расширяется, Number у каждого класса есть метод doubleValue () для использования.

код не будет скомпилирован, если я не введу тип x в RationalN перед выполнением doubleValue ()

, но при выполнении кода он жалуется, когда сравнивается объект другого класса, поскольку он не может быть типизированк этому классу.

И куда мне идти отсюда?

        public class RationalN extends Number{
          private int numerator;
          private int denominator;

          public RationalN(int x, int y){
            if (y == 0){
              throw new ArithmeticException("cannot devide by zero");
            } else {
              this.numerator=x;
              this.denominator=y;
            }
          }

          public double doubleValue(){
            double value = (double)numerator/(double)denominator;
            return (double)value;
          }

          public boolean equals(Object x){
            if (((RationalN)x).doubleValue() == this.doubleValue()){
                  return true;
                } else {
                  return false;
          }
        }

Ответы [ 2 ]

3 голосов
/ 09 ноября 2011

Из того, что я получил из вашего поста, вы хотите проверить, равно ли числовое значение, представленное вашим объектом, равно числовому значению объекта аргумента.Поэтому сравнение классов не целесообразно.Вместо этого ваш метод equals () тоже выглядит примерно так:

public boolean equals(Object x) {
    if(this == x)
        return true;
    if(x == null)
        return false;
    if(!(x instanceof Number))
        return false;
    Number n = (Number)x;
    return (n.doubleValue() == this.doubleValue());
}

Это, однако, нарушает контракт equals (): новый RationalN (1, 1) .equals (new Integer (1))вернул бы true, но new Integer (1) .equals (new RationalN (1, 1));не будет - вышеуказанный метод equals () нарушает симметрию.Поэтому было бы целесообразно ввести абстрактный класс, реализующий Number (скажем, MyNumber), который расширяется только вашими пятью классами и реализует equals () указанным выше способом (используя instanceof MyNumber).

1 голос
/ 09 ноября 2011

edit: я только что понял, что число имеет doubleValue() в качестве абстрактного метода в классе Number. Хорошо, это прекрасно. Просто внедрите равенства во всех пяти классах, как это. В качестве альтернативы, если Number не требуется в качестве абстрактного класса, прочитайте ниже, чтобы увидеть, что вы можете создать свой собственный абстрактный класс, реализующий equals(), и сохранить дублированный код.

public boolean equals(Object x)
{
  if(x instanceof Number == false)
    return false;

  Number other = (Number) x;

  return other.doubleValue() == doubleValue();
}

Причина, по которой вы не можете делать то, что делаете в своих равных, заключается в том, что вы разыгрываете то, с чем пытаетесь сравнить, с классом RationalN. Когда это делается для класса, который не является RationalN, это приводит к исключению ClassCastException.

Поскольку все классы расширяют Number и doubleValue() объявляется как метод, доступный для Number, теперь вы можете преобразовать эти классы в Number (если они являются экземпляром Number) и затем получить доступ к методу оттуда.

Надеюсь, это имеет смысл. Я рекомендую вам прочитать об интерфейсах и полиморфизме.

edit: Кроме того, если вам не требуется расширять Number, вы можете создать абстрактный класс, который имеет абстрактный метод doubleValue(), и затем вы можете предоставить конкретную реализацию equals (которую я предоставил выше) в абстрактный класс. Затем пусть все пять ваших классов расширяют абстрактный класс. Каждый из них затем реализует свою собственную версию doubleValue(), но разделяет equals(), определенный в вашем абстрактном классе, и, таким образом, исключает копирование / вставку equals() во все пять классов. Это был бы идеальный маршрут, если бы вам не нужно было расширять номер.

...