Java дочерний класс, равный родительскому, используя только атрибуты родителя - PullRequest
1 голос
/ 14 апреля 2020

У меня есть следующий родительский класс:

public class Coordinates {
    private int xCoordinate;
    private int yCoordinate;

    public Coordinates(int xCoordinate, int yCoordinate) {
        this(xCoordinate, yCoordinate, 10, false);
    }

    public Coordinates(int xCoordinate, int yCoordinate, int max) {
        this(xCoordinate, yCoordinate, max, false);
    }

    public Coordinates(int xCoordinate, int yCoordinate, int max, boolean allowedZero) {
        if (allowedZero) {
            if ((xCoordinate >= 0 && yCoordinate >= 0) && (xCoordinate <= max && yCoordinate <= max)) {
                this.xCoordinate = xCoordinate;
                this.yCoordinate = yCoordinate;
            } else {
                throw new IllegalArgumentException(String.format("Either X or Y has set to value <= 0, or > %d", max));
            }
        } else {
            if ((xCoordinate > 0 && yCoordinate > 0) && (xCoordinate <= max && yCoordinate <= max)) {
                this.xCoordinate = xCoordinate;
                this.yCoordinate = yCoordinate;
            } else {
                throw new IllegalArgumentException(String.format("Either X or Y has set to value <= 0, or > %d", max));
            }
        }

    }
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Coordinates that = (Coordinates) o;
        return xCoordinate == that.xCoordinate &&
                yCoordinate == that.yCoordinate;
    }

    @Override
    public int hashCode() {
        return Objects.hash(xCoordinate, yCoordinate);
    }

    @Override
    public String toString() {
        return String.format("Coordinates (%d, %d)", xCoordinate, yCoordinate);
    }
}

Я также создал следующий дочерний класс:

public class Segment extends Coordinates {
    private boolean isDestroyed;

    public Segment(int xCoordinate, int yCoordinate) {
        super(xCoordinate, yCoordinate);
        this.isDestroyed = false;
    }

    public Segment(int xCoordinate, int yCoordinate, int max) {
        super(xCoordinate, yCoordinate, max);
        this.isDestroyed = false;
    }

    public Segment(int xCoordinate, int yCoordinate, int max, boolean allowedZero) {
        super(xCoordinate, yCoordinate, max, allowedZero);
        this.isDestroyed = false;
    }

    public boolean isDestroyed() {
        return isDestroyed;
    }

    public void setDestroyed(boolean destroyed) {
        isDestroyed = destroyed;
    }

    @Override
    public boolean equals(Object o) {
        return super.equals(o);
    }

    @Override
    public int hashCode() {
        return super.hashCode();
    }
}

Поскольку «Сегмент» - это просто класс «Координаты» с одним новое поле, я хотел бы, чтобы они были непосредственно сопоставимы друг с другом только через поля X и Y класса "Координаты". Тем не менее, в данный момент я проваливаю тестовый пример junit4, где сравниваю следующее:

    @Test
    public void testSegmentToCoordinateComparison() {
        // Given
        Segment segment = new Segment(1, 1);

        // When
        Coordinates coordinates = new Coordinates(1, 1);

        // Then
        Assert.assertEquals(coordinates, segment);
    }

Выводится следующая ошибка:

expected: package.Coordinates<Coordinates (1, 1)> but was: package.Segment<Coordinates (1, 1)>

Есть идеи?

1 Ответ

1 голос
/ 14 апреля 2020

Таким образом, ваш метод равенства равен

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Coordinates that = (Coordinates) o;
        return xCoordinate == that.xCoordinate &&
                yCoordinate == that.yCoordinate;
    }

Основным нарушителем здесь является getClass() != o.getClass(), поскольку в этом случае getClass равен Coordinates, а o.getClass равен Segment. Вы не хотите сопоставлять классы, вы просто хотите, чтобы все подклассы координат использовали координаты для сравнения. Поэтому попробуйте вместо этого использовать instanceof Coordinates, например,

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        /* What instanceof is telling us here is that a cast to Coordinates
         * won't generate an error because it's the same class, or a subclass
         * or implementing class of Coordinates.
         */
        if (o instanceof Coordinates) { //evaluates to false if o is null 
            Coordinates that = (Coordinates) o;
            return xCoordinate == that.xCoordinate &&
                    yCoordinate == that.yCoordinate;
        } else {
            return false;
        }
    }

Вы получаете бонусные баллы за переопределение hashCode, чтобы отразить ваше намерение сравнивать равенство, что действительно помогло мне понять ваш вопрос:)

...