Разница между интерфейсом и абстрактным классом

👁 79 просмотров

В данной статье я раскрою тему интерфейсов и абстрактных классов, многие особо не видят в них разницу, но, если они есть в ООП, то не зря их включили, чтобы облегчить нам жизнь.

Итак, давайте разберемся с основными понятиями иначе, зачем нам работать на интсрументе, название которого нам непонятно, не так ли? 🙂

Интерфейс (interface) — это некая совокупность возможностей или методов выполнения операций над объектом или объектами;

Абстракция (abstraction) -придание сущности или объекту некоторых конкретных черт, отвергая при этом несущественных;

Т.е. из описаний ясно, что интерфейс оперирует со свойствами и возможностями объекта, когда как абстрактный класс предоставляет саму сущность в корне, наследуя который, мы создаем на его основе все новые и новые родословные сущности.

Именования интерфейсов и абстрактных классов

Если вы хотите создать интерфейс или абстракцию, то следует придерживаться определенной семантики, это конечно, не строгие правила, но очень помогает при решении задачи ибо все упирается в возможности нашего мозга все запомнить, а это проблемное дело в таком деле, как программирование :).

При создании интерфейса им следует давать названия , которые описывают возможности объекта, которые могут обозначать прилагательное или причастие речи,к примеру : Flexible(изгибающийся),  Comparable(сравнимый), Sizeable(масштабируемый) и т.д.

При создании абстракции мы должны исходить из родительской сущности, да, именно из родительской, так как, если мы создаем абстрактный класс, то обязательно на его основе создаем наследование и переопределение его свойств иначе его смысл в ООП потерялся бы и для этого можно использовать существительное,к примеру: Car(машина), Figure(фигура), Wear(одежда), а конкретные реализации, допустим от Car, мы уже будем реализовывать при наследовании через обычные класс.

 

Связь триединства сущности — интерфейс, абстракция, класс.

Теперь давайте подумаем над тем, как формируется связь со всеми этими понятиями. Класс — это конечная возможность любой сущности, вот к примеру: кенгуру не может быть родителем другого класса животных, но он может быть классом сумчатых и класс сумчатых можно реализовать как интерфейс. Еще кенгуру умеет прыгать, пить, есть, размножаться и тогда логично добавить еще интерфейс его возможностей.

Покажем пример:


//Определим абстракцию фигуры
abstract class Figure{
    public $width,$x,$y,$z = 0;
    protected $hight = 0;
    private $size =0;

    const E = 2.7;

    abstract public function fit();
    public function setX($x)
        {
            $this->x=$x;
        }

}
//Определим интерфейс для фигур
interface Sizeable{
    const PI = 3.14;
    function setSize($scale);
}
//
interface Fitable{
    const WHITE = "FFFFFF";
    function setColor($color);
}
//Создадим конкретную сущность, удовлетворяющий вышеописанным условиям
class Rectangle extends Figure implements Sizable, Fitable{

   public function setSize($scale)
     {
           return ['witdh'=>($scale*$this->width),'hight'=>($scale*$this->hight)];
     }
   function setColor($color)
     {
           echo "Setting clor with code ".$color;
     }
}

Основные положения из этого всего.

Основные положения при создании абстрактного класса

1. Абстрактный класс и абстрактный метод создаются с помощью ключевого слова abstract;
2. Абстрактный класс обязательно должен содержать в себе хотябы один абстрактный метод;
3. Реализация абстрактного класса происходит через ключевое слово extends;
4. Класс может реализовать только один абстрактный класс;
5. Абстрактный класс, в отличии от интерфейса, может содержать реализованные методы;
6. Как и обычный класс может содержать поля, константы и методы с реализацией;
7. Абстрактные методы и поля можно объявлять с идентификаторами доступа public, protected, private и ,при реализации в классе, методы должны иметь такой же модификатор или менее ограниченный;
8. Абстрактные методы должны быть указаны явно через ключевое слово abstract;
9. При наследовании все методы, помеченные как абстрактные, должны быть реализованы в классе -потомке и ,при этом , область видимости этих методов должна совпадать (или быть менее строгой);
10. Сигнатуры , реализуемых в классе-потомке, методов должны совпадать, т.е. контроль типов и количество обязательных аргументов должно быть одинаковым;
11. Если в дочернем классе указан необязательный параметр, которого нет в сигнатуре абстрактного класса, то в данном случае конфликта сигнатур не будет. Это правило также применяется к конструкторам начиная с версии PHP 5.4. Это говорит о том, что, если в абстракции у нас метод с 2-мя аргументами, то в наследуемом классе мы можем переопределить этот метод с двумя аргументами или добавить еще, но никак не меньше;
12. Нельзя создать экземпляр или объект абстрактного класса;
13. Методы, объявленные как абстрактные не могут не могут нести реализацию , они имеют только опистельный смысл и должны быть обязательно реализованы в классе наследующим абстракцию;

Основные положения при создании интерфейса

1. Класс не может реализовать 2 интерфейса, у которых одинаковые методы ибо возникнет неоднозначность вызова;
2. Интерфейсы могут быть унаследованы друг от друга, так же как и классы, с помощью оператора extends;
3. Сигнатуры(т.е. количество передаваемых переменных и название метода) методов в классе, реализующем интерфейс, должны точно совпадать с сигнатурами, используемыми в интерфейсе, в противном случае будет вызвана фатальная ошибка;
4. Интерфейсы могут содержать константы. Константы интерфейсов работают точно так же, как и константы классов, за исключением того, что они не могут быть перекрыты наследующим классом или интерфейсом, иначе говоря не могут быть переопределены;
5. Все методы интерфейса, по умолчанию, являются абстрактными;
6. Все методы интерфейса, по умолчанию, являются публичными;
7. Интерфейс не может реализовать содержащиеся в нем методы, реализует наследующий класс;
8. Класс может наследовать интерфейс через ключевое слово implements;
9. Класс может реализвовать и наследовать несколько интерфейсов через запятые и названия интерфейсов;
10. Класс, реализующий интерфейс, должен обязательно реализовать код для всех методов наследуемого интерфейса;