Интерфейсы - это вообще классы без логики, только подпись. В то время как абстрактные классы имеют логику. Оба поддерживают контракт как интерфейсный метод все должны быть реализованы в дочернем классе, но абстрактно должен быть реализован только абстрактный метод. Когда использовать интерфейс и когда абстрагироваться? Зачем использовать интерфейс?
class Circle {
protected $radius;
public function __construct($radius)
{
$this->radius = $radius
}
public function area()
{
return 3.14159 * pow(2,$this->radius); // simply pie.r2 (square);
}
}
//Our area calculator class would look like
class Areacalculator {
$protected $circle;
public function __construct(Circle $circle)
{
$this->circle = $circle;
}
public function areaCalculate()
{
return $circle->area(); //returns the circle area now
}
}
Мы бы просто сделали
$areacalculator = new Areacalculator(new Circle(7));
Через несколько дней нам понадобится площадь прямоугольника, квадрата, четырехугольника и так далее. Если да, нужно ли нам каждый раз менять код и проверять, имеет ли экземпляр квадрат, или круг, или прямоугольник? Теперь, что говорит OCP, это КОДЕКС ИНТЕРФЕЙСА, а не РЕАЛИЗАЦИЯ.
Решение будет:
Interface Shape {
public function area(); //Defining contract for the classes
}
Class Square implements Shape {
$protected length;
public function __construct($length) {
//settter for length like we did on circle class
}
public function area()
{
//return l square for area of square
}
Class Rectangle implements Shape {
$protected length;
$protected breath;
public function __construct($length,$breath) {
//settter for length, breath like we did on circle,square class
}
public function area()
{
//return l*b for area of rectangle
}
}
Теперь для калькулятора области
class Areacalculator {
$protected $shape;
public function __construct(Shape $shape)
{
$this->shape = $shape;
}
public function areaCalculate()
{
return $shape->area(); //returns the circle area now
}
}
$areacalculator = new Areacalculator(new Square(1));
$areacalculator->areaCalculate();
$areacalculator = new Areacalculator(new Rectangle(1,2));
$areacalculator->;areaCalculate();
Разве это не гибче? Если бы мы кодировали без интерфейса, мы бы проверяли экземпляр для каждого избыточного кода формы.
Теперь, когда использовать абстрактный?
Abstract Animal {
public function breathe(){
//all animals breathe inhaling o2 and exhaling co2
}
public function hungry() {
//every animals do feel hungry
}
abstract function communicate();
// different communication style some bark, some meow, human talks etc
}
Теперь абстрактный следует использовать, когда вам не нужен экземпляр этого класса, с похожей логикой, нуждающийся в контракте.