Overriding equals() & hashCode() in sub classes … considering super fields

前端 未结 10 1251
一个人的身影
一个人的身影 2020-12-07 13:19

Is there a specific rule on how Overriding equals() & hashCode() in sub classes considering super fields ?? k

10条回答
  •  轻奢々
    轻奢々 (楼主)
    2020-12-07 13:51

    Well, HomoSapiens#hashcode will be enough with CPerkins's answer.

    @Override     
    public int hashCode() {     
        int hash = super.hashCode();
        hash = 89 * hash + Objects.hash(name);     
        hash = 89 * hash + Objects.hash(faceBookNickname);     
        return hash;     
    }
    

    If you want those parent's fields(gender, weight, height) in action, one way is creating an actual instance of parent type and use it. Thank God, it's not an abstract class.

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final HomoSapiens other = (HomoSapiens) obj;
        if (!super.equals(new Hominidae(
            other.gender, other.weight, other.height))) {
             return false;
        }
        if (!Objects.equals(name, other.name)) return false;
        if (!Objects.equals(faceBookNickname, other.faceBookNickname))
            return false;
        return true;
    }
    

    I'm adding a way to (I think) solve this. The key point is adding a method loosely checks the equality.

    public class Parent {
    
        public Parent(final String name) {
            super(); this.name = name;
        }
    
        @Override
        public int hashCode() {
            return hash = 53 * 7 + Objects.hashCode(name);
        }
    
        @Override
        public boolean equals(final Object obj) {
            return equalsAs(obj) && getClass() == obj.getClass();
        }
    
        protected boolean equalsAs(final Object obj) {
            if (this == obj) return true;
            if (obj == null) return false;
            if (!getClass().isAssignableFrom(obj.getClass())) return false;
            final Parent other = (Parent) obj;
            if (!Objects.equals(name, other.name)) return false;
            return true;
        }
    
        private final String name;
    }
    

    And here comes the Child.

    public class Child extends Parent {
    
        public Child(final String name, final int age) {
            super(name); this.age = age;
        }
    
        @Override
        public int hashCode() {
            return hash = 31 * super.hashCode() + age;
        }
    
        @Override
        public boolean equals(final Object obj) {
            return super.equals(obj);
        }
    
        @Override
        protected boolean equalsAs(final Object obj) {
            if (!super.equalsAs(obj)) return false;
            if (!getClass().isAssignableFrom(obj.getClass())) return false;
            final Child other = (Child) obj;
            if (age != other.age) return false;
            return true;
        }
    
        private final int age;
    }
    

    Testing...

    @Test(invocationCount = 128)
    public void assertReflective() {
        final String name = current().nextBoolean() ? "null" : null;
        final int age = current().nextInt();
        final Child x = new Child(name, age);
        assertTrue(x.equals(x));
        assertEquals(x.hashCode(), x.hashCode());
    }
    
    @Test(invocationCount = 128)
    public void assertSymmetric() {
        final String name = current().nextBoolean() ? "null" : null;
        final int age = current().nextInt();
        final Child x = new Child(name, age);
        final Child y = new Child(name, age);
        assertTrue(x.equals(y));
        assertEquals(x.hashCode(), y.hashCode());
        assertTrue(y.equals(x));
        assertEquals(y.hashCode(), x.hashCode());
    }
    
    @Test(invocationCount = 128)
    public void assertTransitive() {
        final String name = current().nextBoolean() ? "null" : null;
        final int age = current().nextInt();
        final Child x = new Child(name, age);
        final Child y = new Child(name, age);
        final Child z = new Child(name, age);
        assertTrue(x.equals(y));
        assertEquals(x.hashCode(), y.hashCode());
        assertTrue(y.equals(z));
        assertEquals(y.hashCode(), z.hashCode());
        assertTrue(x.equals(z));
        assertEquals(x.hashCode(), z.hashCode());
    }
    

提交回复
热议问题