I start the path of the programmer. They said to learn polymorphism. I started reading from different sources, everywhere it’s not clear. I understand this is a very broad concept that there are 3 main types and each of them is divided into many more types.

I will just write as I understood from what I read and from what my friend suggested. I ask to podravit me if I was mistaken in something. I would be glad if you describe briefly what it is and 3 main types.

I understand there are 3 main types of polymorphism (php examples):

  1. Ad hoc polymorphism - several function declarations with the same name but with different parameters, example:

When a function is called, the type of the argument will be selected.

function test (string $a, string $b) { return $a . $b; } function test (int $a, int $b) { return $a + $b; } // если бы в пхп поддерживалось, то вывело бы test('a', 'b') // 'ab' test(1, 4) // 5 
  1. Parametric polymorphism - when the same function is executed, regardless of the types of arguments.

It is supported in php.

 function test (string $a, string $b) { return $a . $b; } function test (int $a, int $b) { return $a + $b; } // если бы в пхп поддерживалось, то вывело бы test('a', 'b') // 'ab' test(1, 4) // 5 

Parametric polymorphism is a true form of polymorphism, making the language more expressive and significantly increasing the code reuse rate. Traditionally, he is contrasted with ad hoc polymorphism (imaginary form).

  1. Subtype polymorphism - as far as I understand this is the most popular concept of polymorphism.

When there are methods in different classes that do the same, they need to be given the same name and have these classes implement a single interface or inherit a single abstract class with this abstract method.


A little more it is not clear where Subtype is associated with interfaces when the other two are connected with parameters and Parametric is true, and Ad hoc is its imaginary form as I read.

  • 2
    Read [ habr.com/post/37610/] here - dev_null
  • @dev_null, thanks, there's a good example of Subtype polymorphism. Apparently, I understood Subtype correctly, about the other two I am not sure what I wrote as it is. - Sasha Egorov

1 answer 1

Honestly not strong in modern terms, but before that what you brought:

Ad hoc polymorphism

Parametric polymorphism

Called "function / method overload". What's up

Subtype polymorphism

It really is important today. What is the essence - in the comments gave a good link to the article. But it's not cool when non-living examples are given for learning: you won't see this in PHP.

But the examples that I add: I see in PHP every day, and it seems to me they will help to reveal the essence of this concept. In the database of almost every site there are users, articles, photos. For universal work with rows of the database, there is the ActiveRecord pattern, which polyformism uses most clearly. For example, there are classes that describe the rows in the database:

 class User extends ActiveRecord class Article extends ActiveRecord class Photo extends ActiveRecord 

ActiveRecord itself has onboard methods save() , setFromArray() , getId() . Examples of how to work with ActiveRecord :

 //1 $user = new User(1234);//получение юзера с id=1234 из БД $user->first_name = 'Евпатий'; $user->save(); //2 $article = new Article(1234); $article->setFromArray($formdata); $article->save(); echo('Article '. $article->getId(). ' saved'); 

For example, before saving the article specifically, we want to make a trigger and reset the cache, for this we extend the behavior of the save method:

 class Article extends ActiveRecord { ... public function save() { $this->resetSomeArticleCache(); return parent::save(); } } 

Thus, somewhere in the code there may be a universal controller whose task is to update a certain field, which many records have:

 public function upgradeModifyDateAction() { $type = $_GET['type']; $id = (int)$_GET['id']; //полиморфное получение ряда тут максимально наглядно описано, обычно это как-то Core::getRow($type, $id) if (is_subclass_of($type, 'ActiveRecord') && ($row = new $type($id)) && $row->isExists() && $row->fieldExists('modify_date') ){ $row->modify_date = date('Ymd H:i:s'); $row->save();// !! полиформизм здесь !! }else{/*ошибка*/} } 

The bottom line is that the controller does not really care which ActiveRecord specifically asked to update, and if the object has “special behavior” to be updated, then it will be executed: that is, the resetSomeArticleCache method will be resetSomeArticleCache for the article in the example. At the same time, special behavior is transparent to the controller - this is the essence.

The main point is to save the programmer’s memory when using polymorphism: Imagine that there are not 3, but 100 different ActiveRecords in the system. To work with one of such objects (or a group), you don’t need to remember either the name of the table in which it is stored, or the name of the id column, you don’t need to think whether the list of objects is homogeneous before chasing it in a cycle: just remember that there is a getId() method getId() which returns id, and there is a save() method - which saves the object in the database.

As well as it is not necessary to think about the fact that "this is so, and if I update the article in the code, I also need to clean the cache", insert unnecessary if -s. Therefore, this is important - it is easier to live with polymorphism, to say that this is something special cannot be, today this concept is generally inseparable from inheritance in any modern world. languages.

Speaking about the types of polymorphism, in PHP they often use " duck polymorphism " - some consider it antipattern, and some praise it. For me, it is moderately useful:

 /*например функция проверки прав $user на $object*/ public function checkRights($user, $object, $right = 'edit') { ... if (method_exists('isExtraAllowed', $object)){ if (($result = $object->isExtraAllowed($user, $right)) != self::IGNORE) return $result; } ... } 

In the example, the fact is that it would be blasphemous to get the basic isExtraAllowed in ActiveRecord , since ActiveRecord does not belong to rights in principle - and we will spread a clear class to ourselves. And the need to add such a duck-polymorphic insert as isExtraAllowed occurs in real projects in my memory always (where, of course, the OOP is widely used), especially if the ACL rights system was introduced far after the start of the project.
Yes, in the example it would be possible to add an interface instead of the duck approach, calling for example IACLExtendedProvider , but firstly it will score a global list of classes and interfaces (and the programmer’s brain at the same time), secondly a programmer who is not used to interfaces will go into a stupor when it will not understand why the isExtraAllowed method added by it isExtraAllowed not work.