Переопределение равняется () и хэш-код () в sub классах … рассмотрение супер полей

Есть ли определенное правило о как Переопределение equals() & hashCode() в sub классах, рассматривая супер поля?? знание, что существует много параметров: супер поля являются частными/общедоступными, с/без методом get...

Например, Netbeans генерировал, равняется (), и хэш-код () не рассмотрит супер поля... и

    new HomoSapiens("M", "80", "1.80", "Cammeron", "VeryHot").equals(
    new HomoSapiens("F", "50", "1.50", "Cammeron", "VeryHot"))

возвратит true: (

public class Hominidae {

    public String  gender;
    public String  weight;
    public String  height;

    public Hominidae(String gender, String weight, String height) {
        this.gender = gender;
        this.weight = weight;
        this.height = height;
    }
    ... 
}

public class HomoSapiens extends Hominidae {
    public String name;
    public String faceBookNickname;

    public HomoSapiens(String gender, String weight, String height, 
                       String name, String facebookId) {
        super(gender, weight, height);
        this.name = name;
        this.faceBookNickname = facebookId;
    }
    ...  
}

Если Вы хотите видеть, что сгенерированные Netbean равняются () и хэш-код ():

public class Hominidae {

    ...

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Hominidae other = (Hominidae) obj;
        if ((this.gender == null) ? (other.gender != null) : !this.gender.equals(other.gender)) {
            return false;
        }
        if ((this.weight == null) ? (other.weight != null) : !this.weight.equals(other.weight)) {
            return false;
        }
        if ((this.height == null) ? (other.height != null) : !this.height.equals(other.height)) {
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        int hash = 5;
        hash = 37 * hash + (this.gender != null ? this.gender.hashCode() : 0);
        hash = 37 * hash + (this.weight != null ? this.weight.hashCode() : 0);
        hash = 37 * hash + (this.height != null ? this.height.hashCode() : 0);
        return hash;
    }

}


public class HomoSapiens extends Hominidae {

    ...

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final HomoSapiens other = (HomoSapiens) obj;
        if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) {
            return false;
        }
        if ((this.faceBookNickname == null) ? (other.faceBookNickname != null) : !this.faceBookNickname.equals(other.faceBookNickname)) {
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 89 * hash + (this.name != null ? this.name.hashCode() : 0);
        hash = 89 * hash + (this.faceBookNickname != null ? this.faceBookNickname.hashCode() : 0);
        return hash;
    }
}
62
задан wj. 14 January 2010 в 19:26
поделиться

6 ответов

Дети не должны рассматривать частных членов своих родителей

, но , очевидно, , все значимые поля следует учитывать для равенства и хеширования.

К счастью, вы можете легко удовлетворить оба правила.

Предполагая, что вы не застряли с использованием сгенерированных NetBeans Equals и HASHCODE, вы можете изменить метод SominiDae Socals для использования экземпляров сравнения, а не равенства класса, а затем использовать его прямолировку. Что-то вроде этого:


    @Override  
    public boolean equals(Object obj) {  
        if (obj == null) { return false; }  
        if (getClass() != obj.getClass()) { return false; }  
        if (! super.equals(obj)) return false;
        else {
           // compare subclass fields
        }

, конечно, Hashcode легко:


    @Override     
    public int hashCode() {     
        int hash = super.hashCode();
        hash = 89 * hash + (this.name != null ? this.name.hashCode() : 0);     
        hash = 89 * hash + (this.faceBookNickname != null ? this.faceBookNickname.hashCode() : 0);     
        return hash;     
    }     

серьезно, хотя и: что случилось с NetBeans, не принимая вклад в SuperClass на счет, вызывая методы SuperClass?

56
ответ дан 24 November 2019 в 16:49
поделиться

Я предпочитаю использовать EqualsBuilder (и HashcodeBuilder) от пакет Ленга свободного городского населения для создания, мой равняется () и хэш-код () методы, намного легче читать.

Пример:

public boolean equals(Object obj) {
 if (obj == null) { return false; }
 if (obj == this) { return true; }
 if (obj.getClass() != getClass()) {
   return false;
 }
 MyClass rhs = (MyClass) obj;
 return new EqualsBuilder()
             .appendSuper(super.equals(obj))
             .append(field1, rhs.field1)
             .append(field2, rhs.field2)
             .append(field3, rhs.field3)
             .isEquals();
}
20
ответ дан 24 November 2019 в 16:49
поделиться

Правила:

  • Это рефлексивно: для любого ненульного эталонного значения X, x.equals (x) должны вернуть true.
  • Это симметричный: для любых ненульных ссылочных значений X и Y, X.equals (y) должны вернуть true, если и только если y.equals (x) возвращает true.
  • Это транзитивно: для любого ненулевых ссылочных значений x, y и z, если x.equals (y) возвращает true, и y.equals (z) возвращает true, то x.equals (z) должен вернуть true Отказ
  • Это согласуется: для любых ненульных ссылочных значений X и Y, несколько вызовов X.equals (y) последовательно возвращают истинные или последовательно возвращающие ложные, при условии, что информация, используемая в сравнениях равенства на объектах, не модифицирована.
  • Для любого ненулевого эталонного значения X, X.equals (NULL) следует вернуть false.
  • , как правило, необходимо переопределить метод HASHCODE всякий раз, когда этот метод является переопределенным, чтобы поддерживать общий договор на метод HASHCODE, который гласит, что равные объекты должны иметь равные хешиные коды

из объекта. ) .

Итак, используйте поля, необходимые для выполнения правил.

6
ответ дан 24 November 2019 в 16:49
поделиться

Это звучит, как ваш родительский (супер) класс не отменяет равных. Если это так, то необходимо сравнить поля из родительского класса при переопределении этого метода в подкласс. Я согласен, что использование Commons Equalsbuiler - это способ пойти, но вам нужно быть осторожным, что вы не нарушаете симметрию / трансваторные части контракта равен.

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

Я настоятельно рекомендую раздел в эффективной Java by Jowsua Block на этом. Это всеобъемлющее и действительно хорошо объяснено.

1
ответ дан 24 November 2019 в 16:49
поделиться

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

2
ответ дан 24 November 2019 в 16:49
поделиться

Вообще говоря, реализующие равные подклассы, трудно сохранить симметричное и транзитивное.

Рассмотрим суперкласс, который проверяет поле x и Y , а также проверки подкласса x , y и z .

Таким образом, подкласс == SuperClass == подкласс, где Z отличается между первым экземпляром подкласса и вторым, нарушающим переходную часть контракта.

Это, почему типичная реализация равна будет проверять GetClass ()! = Obj.getclass () вместо того, чтобы делать экземпляр. В приведенном выше примере, если подкласс или суперкласс делает экземпляр проверки, он сломал бы симметрию.

Итак, в том, что подкласс, безусловно, может учитывать Super.equals (), но также должен сделать свой собственный чек GetClass (), чтобы избежать вышеуказанных проблем, а затем проверять наличие равных полей. Это была бы странная утка класса, которая изменила свои собственные равные поведения на основе определенных полей суперкласса, а не только если суперкласс возвращается равным.

8
ответ дан 24 November 2019 в 16:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: