A
A
Anton R.2019-09-02 00:07:20
OOP
Anton R., 2019-09-02 00:07:20

Do I understand the essence of Interfaces in OOP correctly?

I am reading the book by Matt Zandstra "PHP. Objects, patterns and programming techniques" (5th edition 2019), I got to the section about Interfaces and specifically got stuck at the stage of understanding how it works and why, especially since this thing is given 4 pages there (at least the basics), I understood little, re-read it three times and got on the Internet to dig for alternative explanations. Based on Matt's description, I realized that the simple phrase "interfaces are required to implement all of the listed methods" is not enough, something more complex, useful and interesting is hidden there.
In principle, now I understand what Matt meant, but it was hard right away, so I managed to code for Understanding interfaces (and how I understood the Essence of Interfaces):

<?php

// Интерфейс - включить музыку.
interface PlayMusic{
  
  public function PlayMusic();
  
}

// Реализация метода Включить музыку - через CD-диск
class CdPlayer implements PlayMusic{
  
  private $cd;
  
  public function PlayMusic($cd){
    $this->cd = $cd;
    $this->cd->play();
  }
}

// Реализация метода Включить музыку - через радио
class RadioPlayer implements PlayMusic{
  
  private $fm;
  
  public function PlayMusic($fm){
    $this->fm = $fm;
    $this->fm->play();
  }
}

// Класс-клиент принимающий в конструкторе класс-сервис и использующий реализованные в классе-сервисе методы.
class MusicCenter{
  
  public $player;
  
  public function __construct(PlayMusic $player){
    $this->player = $player;
  }
}


// Создание класса-сервиса $player - проигрывать диск.
$player_1 = new CdPlayer('cd1');

// Создание класса-сервиса $player - включить радио.
$player_2 = new RadioPlayer('105.9');


//Создание класса-клиента $musiccenter который проигрывает диск.
$musicCenter_1 = new MusicCenter($player_1);
//Вызов метода класса-сервиса в классе-клиенте
$musicCenter_1->$this->player->Playmusic();


//Создание класса-клиента $musiccenter который включает радио.
$musicCenter_2 = new MusicCenter($player_2);
//Вызов метода класса-сервиса в классе-клиенте
$musicCenter_2->$this->player->Playmusic();

?>

BASIC concepts to consolidate Understanding (I actually wrote it down in a summary, for myself):
The client class does not know exactly how the music is turned on, it is important for him to turn on the music, for this he is given a service class that implements this action in its own way (for example, we press a certain button at the Music Center).
Action structure: Client class -> Service class -> implemented method.
A client class cannot accept a service class if it is not of a Type defined by an Interface.
(for example, we cannot turn on music by pressing the power button or some other method that does not implement the method of turning on music, for example, the "open disc tray" button).

The creation of an interface results in the creation of a new Class Type according to the name of the Interface (from the book by Matt Zandstra).
As a result, we have 4 types of Class:
1 type - PlayMusic - aka Interface.
Type 2 - CdPlayer - service
Type 3 - RadioPlayer - service
Type 4 - MusicCenter - client
You can of course laugh, but I even drew this "on a napkin" while thinking everything over and trying to understand :)
5d6c327112288129385866.jpeg
And the final question - WHY do interfaces? Just to separate once again the logic from the implementation?

Answer the question

In order to leave comments, you need to log in

3 answer(s)
C
coderisimo, 2019-09-02
@coderisimo

Interfaces are like contracts. That is, if a class implements an interface, then it fulfills our contract. It's comfortable! For example, there is a class TaxCollector , it accepts a class that implements the moneySource interface. Let's say we now have only two classes (Businessman , Criminal) that we can pass to the TaxCollector and each implements getMoney. Then we can add a dozen more and our TaxCollector will also work well with them. Nothing will change for him. This is because the moneySource interface is strictly defined and includes a getMoney method. Nothing else matters. Any of the classes - Student, Man, Woman, Professor, Gigolo that support this interface are suitable for working with TaxCollector. This is guaranteed by the moneySource interface.

M
Maxim Fedorov, 2019-09-04
@Maksclub

The interface is the basis of polymorphism.
There is one interface, a certain code can work with it. Voila, any implementation of this interface is suitable for this very code.
Example: there is a certain order class Order , it works with a certain sender Sender , we can hard "teach" it to work with it in the code of this Order , or we can simply pass the sender to it through the constructor (hello DI), but do not pass the class / implementation itself , but only its abstraction - the interface, what will be sent, but how - it does not matter, it will be SenderInterface .
Now we can use polymorphism in Order: use any Sender that implements this same SenderInterface
The code:

interface SenderInterface
{
     public function send(): void {};
}

class Order
{
     // тут будет любой, но обязан реализовать SenderInterface
     private $sender;

     public function __constuctor(SenderInterface $sender) {
          $this->sender = $sender;
     }
 
     public function save(): void 
    {
        // какой в приватном поле сидит, тот и отправит, 
        // а кто -- текущему объекту все равно, это есть инверсия зависимости 
        // и принцип единственной ответственности, данный класс не отправляет, а поручает
        $this->sender->send();
    }
}

class MailSender implement SenderInterface
{
     public function send(): void
     {
           // тут отправка почтой
     }
}

class TelegramSender implement SenderInterface
{
     public function send(): void
     {
           // тут отправка телегой
     }
}


// Пример полиморфной работы Order
$order = new Order(new TelegramSender());
$order->save(); // тут отправка телеграмом

$order = new Order(new MailSender());
$order->save(); // тут отправка mail

As you can see, we can add new senders, do something in them, but we will work with the order as before $order->save(), and generally do not touch its code.
Any class has an interface (public / private), the interface is inherited from an abstract / ordinary class by a child (besides that it inherits behavior), why polymorphism is sometimes (in fact, very often) explained precisely on the inheritance of a single class and multiple implementation in the form of children. In fact, it's all about this very interface.

S
stictt, 2019-09-02
@stictt

I won’t speak for the subtleties of PHP, but in general the direction is right. First of all, the interface performs 2 roles, it is the class interaction interface and upcasting. The interaction interface is all public members and methods of the class in their entirety that can be accessed, the interface structures one interaction interface for all classes, as the person said above, by agreement. But this is only a small part of the advantages, the main strength is Upcast, bringing from the particular to the general. Roughly speaking, you assigned the implementation of the interface to the class, then you can cast the class to the interface, and declare the type of the interface by assigning to a variable any class that will have an implementation of the interface, so we get a very dynamic system that can change the implementation, behavior, and much more , without changing the code, on only one interaction interface. You have 100500 classes, and you can access them in exactly the same way, you do not need to register for each type. for each other object, a call to purely its methods.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question