воскресенье, 19 марта 2017 г.

java Interface vs. Abstract

Предисловие


Классом называется класс, когда у него есть имя и реализованы все имеющиеся методы, которые объявлены во всей иерархии классов. Иерархия вместе с ее супертипом становятся более общим преставлением действующего  домена, и, наконец, выходят за пределы этой границы и заканчиваются тем фактом, что почти все является объектом(Очень странное предложение). Суперкласс может быть конкретным классом,  который, очевидно, не final или абстрактным классом,  или  даже одним или несколькими интерфейсами. Комбинирование супер-класса или абстрактоного класса с интерфейсами так же широко известный способ описания класса. Полиморфизм появляется, когда более чем один класс реализует определенный метод различно, в зависимости от назанчения класса. В этой статье рассматривается два из трех супертипов, выделены их основные харрактеристики.  Интерфейс и абстрактный класс могут быть созданые экземпляром анонимного класса.

Абстрактный класс


Обычно, абстрактный класс реализует общее поведение и переменные любого конкретного класса и его методы могут быть уже указаны в интерфейсе. Различимое поведение достигается через объявление абстрактных методов, которые необходимо реализовать в определенном классе.  Абстрактный класс может наследовать поведение от других абстрактных или конкретных классов и может обогащать дальнейшее поведение при добавлении интерфейса. В java такие реализации могут быть явно подчеркнуты с помощью аннотации Override, которая информирует об изменении. Полиморфизм останавливается в тот момент, когда реализация метода становится final. Методы в абстрактном классе могут быть private, это делает такой класс  более подходящим для инкапсуляции private методов, в то же время позволяя рабить  сложные методы на мелкие части. Абтрактный класс очень близок к конкретной реализации класса.

Интерфейс


C Java 1.8 интерфейсы могут реализовывать default методы, для обеспечения общего поведения. Следовательно и абстрактный класс и интерфейс  имеют свой подход, в отношении своих особенностей. Для переменных интерфейса явно указано, что они public и final, а у  переменных абстрактного класса могут быть различные модификаторы доступа. Более того, есть небольшая разница в возможности повлиять на модификатор доступа для default метода. Он всегда public, а у абстрактного класса, реализация может быть с любым доступом (public, protected, default, private). Все, что объявлено в интерфейсе, везде доступно  и может расширяться объектом со специфическим поведением. Интерфейс позволяет наследоваться только от другого интерфейса. И интерфейс и абстрактный класс могут реализовывать статические методы. Другой тип интерфейса  - интерфейс, который не декларирует ни одного метода и применяется как интерфейс-индикатор.Они просто указывают на договор с разработчиком, например, что класс клонируемый или сериализуемый.

Пример 1


Это сравнение подчеркивает преимущество абстрактного класса над интерфейсом, ориентированным на вычисление угла между двумя прямыми. Однако для этой цели можно использовать и интерфейс, и абстрактный класс, в то время как первый не согласуется с предложениями Мартина о чистом коде.
public interface TwoDimensional {
    double PI = 3.141579; //is public and final
    default double getAngle(TwoDimensional a, TwoDimensional b) /* is public */{
        double alpha = 0.0;
        //do complex calculation here
        //modulus
        //scalar
        //to degrees
        return alpha;
    }
    int getX(); //is public
    int getY();
}

public abstract class AbstractTwoDimensional {
    public final double PI = 3.141579;
    private int x;
    private int y;
    public final double getAngle(AbstractTwoDimensional other) {
        double a = calcModulus(x, y);
        double b = calcModulus(other.getX(), other.getY());
        double s = scalar(other.getX(), other.getY());
        return toDegrees(s, a, b);
    }
    private double toDegrees(double s, double a, double b) {
        //compute
        return 0;
    }
    private double calcModulus(int x, int y) {
        //compute...
        return 0;
    }
    private double scalar(int x2, int y2) {
        //compute...
        return 0;
    }
    abstract int getX();
    abstract int getY();
    //some other abstract methods…
}

Пример 2


Этот пример очень близок к предыдущему, но отличается сочетанием интерфейса и абстрактных классов. Оба они характеризуют конкретные классы.
public interface TwoDimensional {
    Double PI = 3.141579;
    double getAngle(TwoDimensional other);
    int getX();
    int getY();
}

public abstract class AbstractTwoDimensional implements TwoDimensional {    
    private int x;
    private int y;
    @Override
    public final double getAngle(TwoDimensional other) {
        double a = calcModulus(x, y);
        double b = calcModulus(other.getX(), other.getY());
        double s = scalar(other.getX(), other.getY());
        return toDegrees(s, a, b);
    }
    @Override
    public final int getX() {
        return x;
    }
    @Override
    public final int getY() {
        return y;
    }
    protected void setX(int x) {
        this.x = x;
    }
    protected void setY(int y) {
        this.y = y;
    }
    private double toDegrees(double s, double a, double b) {
        //compute
        return 0;
    }
    private double calcModulus(int x, int y) {
        //compute...
        return 0;
    }
    private double scalar(int x2, int y2) {
        //compute...
        return 0;
    }
}

public class MutableLine extends AbstractTwoDimensional {
    //some specific things…
    public MutableLine(ImmutableLine line) {
        //extract data and init
    }
}

public final class ImmutableLine extends AbstractTwoDimensional {
    //some specific things...
    public ImmutableLine(MutableLine line) {
        //extract data
    }
    @Override
    public final void setX(int x) {
        //throw an appropriate exception
    }
    @Override
    public final void setY(int y) {
        //throw an appropriate exception
    }
}
PS это мой перевод данной статьи

Комментариев нет :

Отправить комментарий