Переопределить методы равенства и хэш-кода суперкласса.Я делаю для подкласса - PullRequest
1 голос
/ 13 декабря 2011

У меня есть суперкласс с 2 переменными экземпляра (скажем, int a и int b) и теперь решили, что мне нужно иметь одну переменную экземпляра в моем подклассе int c.

Я переопределил метод равенства суперкласса и метод hashCode, чтобы учесть равенство объектов / ценностей. Я также переопределил суперкласс toString, чтобы дать строку представляющий состояние объектов (значения переменных).

Исходя из вышеизложенного и того факта, что у меня теперь есть одна переменная экземпляра int c в моем подклассе Мне было интересно, если я

  1. необходимо переопределить метод toString в подклассе или это нет, поскольку у меня есть допустимый наследуемый метод toString (уже переопределенный) в суперклассе, который можно использовать для представления строки подкласса?
  2. необходимо переопределить метод equals в подклассе. Это можно сделать вызывая метод equals суперкласса и добавляя код сравнения для моей переменной экземпляра подкласса после вызова, или это требует новой реализации? Я полагаю, последний?
  3. Я собирался переопределить метод hashCode в подклассе. Опять же, лучше ли иметь новую реализацию, чем вызывать метод hashCode суперкласса? Я собирался в сравнить a, b и c в методе equals подкласса с другим объектом, а также создать хеш-коды для b и c в методе hashCode подкласса? Это путь или требует, чтобы я рассматривал только переменную c в подклассе как равные и методы хэш-кода?

Я просматривал различные ресурсы, включая Effective Java by bloch (глава 3), но не смог найти ответ на поставленные выше вопросы

Ответы [ 4 ]

3 голосов
/ 13 декабря 2011

Этот ответ предполагает, что ваш класс выглядит следующим образом:

public class MySuperClass {
    int a,b;
}

public class MySubClass extends MySuperClass {
    int b;
}

Во-первых, ваши комментарии относительно toString() не имеют отношения к основным вопросам. В любом случае, ваш код никогда не должен полагаться на реализацию toString - ее вывод только для людей. Не стесняйтесь использовать Super Impl:

public String toString() {
    return super.toString() + ", c=" + c;
}

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

public boolean equals(Object o) {
    // The super equals() will compare int a and int b for us
    if (!super.equals(o)) {
         return false;
    }
    // super thinks it is equal, so let's compare int c
    return o instanceof MySubClass && ((MySubClass)o).c == c;
}

В-третьих, hashcode должен совпадать с равными, так что реализуйте это тоже. Опять же, вы можете использовать impl супер, который хэширует a и b:

public int hashcode() {
    return super.hashcode() + new Integer(c).hashCode(); // for example
}
1 голос
/ 13 декабря 2011

Пока все в подклассе существует в суперклассе, нет необходимости переопределять их (если, конечно, вам не нужны другие функции).

По сути, переопределяйте метод, только если вы хотитеразличные функциональные возможности для каждого подкласса.

Но, конечно, вы сказали, что у вашего подкласса есть новая переменная, int c.В этом случае вам необходимо переопределить метод, чтобы иметь полную функциональность, особенно для equals() и hashCode().

0 голосов
/ 13 декабря 2011

Если вы хотите правильно представить хеш объекта, вам нужно переопределить как equals, так и hashCode.Если вы не переопределите hashCode (), тогда объекты, которые отличаются только разницей в вашем новом поле c , будут помещены в одно и то же хеш-хранилище (и если вы переопределите hashCode, то вы должны переопределить equals, так как два равныхобъекты должны иметь одинаковый хэш).Ваша реализация hashCode может использовать реализацию суперклассов и добавить ее к дополнительным полям подкласса.

К сожалению, невозможно написать строго правильную функцию равенства для класса, который подклассирует неабстрактный класс идобавляет новое поле к нему.Вы либо в конечном итоге нарушите некоторые договорные свойства равных, либо создадите подклассы, которые только добавляют методы, и в конечном итоге окажутся неравными.

Рекомендуемый способ обойти это - не создавать подкласс для добавления полей, а вместо этогосоздать составной класс, который включает в себя экземпляр родительского класса, а также новые поля, а также экспортирует представление включенного класса, чтобы его можно было сравнить при необходимости.

0 голосов
/ 13 декабря 2011

Это зависит от того, что вы пытаетесь изобразить, и что в настоящее время делают ваши методы equals и hashCode.Вам не нужно переопределять, если вы не хотите, чтобы новые поля, добавленные подклассом, учитывались, или , если ваши методы суперкласса не устойчивы к возможности расширения класса (например, сравнениеobj.getClass() вместо использования instanceof).

...