Написание метода equals внутри абстрактного класса - PullRequest
3 голосов
/ 23 апреля 2019

Так что это скорее концептуальный вопрос.У меня есть Абстрактный класс A, а Классы B и C расширяются A.

И B, и C имеют только 1 переменную экземпляра с именем var в обоих классах, иу обоих есть .getVar методы.Объект равен экземпляру B, если этот объект является экземпляром B, и оба экземпляра имеют равные значения для var.То же самое верно для C.

Есть ли способ, которым я могу написать метод .equals(Object object) внутри моего класса Abstract, чтобы мне не нужно было писать, что в основном является тем же методом с той же функциональностьюв обоих классах?

Ответы [ 2 ]

0 голосов
/ 23 апреля 2019

По сути, то, что вы ищете, это способ определения абстрактного метода getVar в родительском классе A и предоставление реализаций в ваших подклассах B и C с родительским классом 'equals метод в зависимости от значения, возвращаемого getVar.Это усложняется тем фактом, что каждый подкласс может иметь различный тип возвращаемого значения для getVar.

. Решение состоит в том, чтобы сделать A универсальный класс, позволяющий возвращать самому типу возвращаемого значения getVarродовой.Затем вы можете просто ссылаться на метод getVar из equals, не беспокоясь о его конкретном типе:

public abstract class A<T> {
    public abstract T getVar();

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + getVar().hashCode();
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null) return false;
        if (getClass() != obj.getClass()) return false;

        A<?> other = (A<?>) obj;
        return getVar().equals(other.getVar());
    }
}

В приведенном выше примере вы заметите, что getVar возвращает универсальный тип T.Это будет указано при определении ваших подклассов:

public class B extends A<Integer> {
    private int var = 0;
    public B(int var) { this.var = var; }

    @Override
    public Integer getVar() { return var; }
}

public class C extends A<String> {
    private String var = "";
    public C(String var) { this.var = var; }

    @Override
    public String getVar() { return var; }
}

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

public class Tester042219 {
    public static void main(String[] args) {
        B x = new B(1);
        B x2 = new B(1);
        B x3 = new B(99);

        System.out.println("B == B: Works? " 
            + (x.equals(x2) && !x.equals(x3)));

        C y = new C("A");
        C y2 = new C("A");
        C y3 = new C("AAAA");

        System.out.println("C == C: Works? " 
            + (y.equals(y2) && !y.equals(y3)));
    }

    public static abstract class A<T> {
        public abstract T getVar();

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + getVar().hashCode();
            return result;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) return true;
            if (obj == null) return false;
            if (getClass() != obj.getClass()) return false;

            A<?> other = (A<?>) obj;
            return getVar().equals(other.getVar());
        }
    }

    public static class B extends A<Integer> {
        private int var = 0;
        public B(int var) { this.var = var; }

        @Override
        public Integer getVar() { return var; }
    }

    public static class C extends A<String> {
        private String var = "";
        public C(String var) { this.var = var; }

        @Override
        public String getVar() { return var; }
    }

}
0 голосов
/ 23 апреля 2019

Предполагая, что A имеет метод abstract getVar(), который как B, так и C обеспечивают реализацию, мы можем использовать это в A#equals при уравнении двух объектов.Поскольку только объекты типа B могут быть равны другому объекту типа B (то же самое относится и к C), мы можем просто сравнить классы каждого объекта;если классы различаются, то они не могут быть равными.

// You didn't specify what type 'var' is.
// B and C both have an implementation for this method.
public abstract T getVar();

@Override
public final boolean equals(Object o) { // Is final so B and C can't override it.
    if (o == null) {
        return false;
    }

    if (getClass() != o.getClass()) {
        // This will ensure that B cannot be equal to C or A, and vice versa.
        return false;
    }

    // o must be of the type B or C, so it's safe to cast to A here.
    return getVar().equals(((A) o).getVar());
}
...