Главная > opinion, programming > Extends only abstract classes

Extends only abstract classes

In this note we will consider an antipattern of a deeper class hierarchy in Java. We need to extend a real (no abstract) class extremely seldom. This practice assists to appear programming errors and characterize weakness of an architecture. Current advice restricts a classes hierarchy by a first real class.

Lets consider a next example from Joshua Bloch «Effective Java. Programming Language Guide» beautiful book:

public class Point {
    private int x, y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

public class ColorPoint {
    private Color color;

    public ColorPoint(int x, int y, Color color) {
        super(x, y);
        this.color = color;
    }
}

Every domain essence must have a class and consists in a class hierarchy from theory viewpoint. A color point is a point and the example’s hierarchy corresponds to theory. But it is necessary to avoid above example in practics. The Point class is real and can have instances and therefore must implements equals and hashCode methods from the invisible parent Object class. The ColorPoint must impelemts these methods too, but it is impossible!

There isn’t a way to extend a real Point class and to overwite the equals method without that agreement will be broken in practics. There are three main agreements in the Bloch’s book or the javadoc commentary to the java.lang.Object class: symmetry, transitivity and consistency.

The Adapter pattern exists for this problem:

public class ColorPoint {
    private Point point;
    private Color color;

    public ColorPoint(int x, int y, Color color) {
        point = new Point(x, y);
        this.color = color;
    }

    public final Point asPoint() {
        return point;
    }
}

But now the ColorPoint class is not a point! Following example presents a solution of the problem and shows deferences between theory (the first example) and practical (the below example) implementations:

public interface Point {
    int getX();
    int getY();
}

public interface Color {
    Color getColor();
}

public interface ColorPoint extends Point, Color {
}
public PointImpl implements Point {
    ...
}

public ColorPointImpl implements ColorPoint {
    private Point point;
    ...
}

We have eliminated the antipattern about extending a real class and received more testability and expandability architecture as a result.

Antipattern UML class diagram

Possible variant UML class diagram

See elso another blog entry about discussed antipattern: Why you should use composition instead of inheritance.

Реклама
Рубрики:opinion, programming
  1. Комментариев нет.
  1. No trackbacks yet.

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s

%d такие блоггеры, как: