This article is linked to pilishen.com—-. Welcome to learn php&Laravel with Pilishen; Study group: 109256050

This article is an extended reading of the chapter of “Laravel Underlying Core Technology Practical Revelation” and “Laravel Underlying Core Concept Analysis”. Considering the basic differences of students, in order to avoid too detailed and lengthy videos, some PHP knowledge points related to laravel’s underlying implementation are presented in the form of articles for preview and reference at any time.

In object orientation, polymorphism is a fundamental and powerful tool to better organize your application development.

What is a Polymorphism?

Polymorphism describes a pattern in object oriented programming in which classes have different functionality while sharing a common interface. Polymorphism, as a design pattern in object-oriented programming, refers to the fact that classes can be implemented in different ways (i.e. in many forms) by following the same interface.

One of the beauties of polymorphism is that you don’t need to know which classes are operating behind them, and although they all do different things, as long as they implement the same interface, they all work the same.

In physical reality, we can think of polymorphism as “pushing a button” — an individual knows how to touch a button, and although different buttons do different things, as long as it’s a button, it’s very simple to operate.

Similarly, in the programming world, polymorphisms allow our programs to be more modular and extensible, rather than being riddled with conditionals based on different states, such as switching at every turn or nesting if judgments at every turn, in which case, nine times out of ten, your code is “broken”.

Interfaces(in a broad sense)

A key link in polymorphism is the interface. Interfaces in broad sense include interface and Abstract class

interface

Any class that implements this interface must implement all of the abstract methods defined in the interface. A class can implement multiple interfaces

interface MyInterface {
    public function doThis();
    public function doThat();
    public function setName($name);
}
Copy the code
// Class MyClass implements MyInterface {protected$name;
    public function doThis() {
        // code that does this
    }
    public function doThat() {
        // code that does that
    }
    public function setName($name) {
        $this->name = $name; } // Invalid method class MyClass implements MyInterface {// missingdoThis () method. privatefunction doThat() {// This method must also be public! } publicfunction setName() {// The name argument is missing! }}Copy the code

Abstract Class

Abstract Class can be said to be between interface and ordinary Class. It can define a unified interface in the form of Abstract method and define specific function implementation. A generic Class that extends the Abstract Class must implement all of the Abstract methods of the Abstract Class.

abstract class MyAbstract {
    public $name;
    public function doThis() {
        // do this
    }
    abstract public function doThat();
    abstract public function setName($name);
}
Copy the code

Step 1: Problems you face

Suppose you have an articleclass:

class Article {
    public $title;
    public $author;
    public $date;
    public $category;
 
    public function  __construct($title.$author.$date.$category = 0) {
        $this->title = $title;
        $this->author = $author;
        $this->date = $date;
        $this->category = $category; }}Copy the code

Now, you want to add a method that outputs article related information in a different format, such as XML or JSON.

This is what you might initially want to do:

class Article {
    //...
    public function write($type) {
        $ret = ' ';
        switch($type) {
            case 'XML':
                $ret = '<article>';
                $ret. ='<title>' . $obj->title . '</title>';
                $ret. ='<author>' . $obj->author . '</author>';
                $ret. ='<date>' . $obj->date . '</date>';
                $ret. ='<category>' . $obj->category . '</category>';
                $ret. ='</article>';
                break;
            case 'JSON':
                $array = array('article'= >$obj);
                $ret = json_encode($array);
                break;
        }
        return $ret; }}Copy the code

Functionally it works, but it looks terrible, doesn’t it? What if, in the future, you want to add other formats? Add a couple of case judgments, how bloated is this code?

One of the most important principles of object orientation is that a class should only do its job. You should be alert whenever you encounter a block of conditional judgments, because chances are you’re already trying to do too many things under the same class or method. So at this point, it’s time to try polymorphic implementation.

Step 2: Define an Interface

interface Writer {
    public function write(Article $obj);
}
Copy the code

Step 3: Implement Interface

XMLWriter can be implemented like this:

class XMLWriter implements Writer {
    public function write(Article $obj) {
        $ret = '<article>';
        $ret. ='<title>' . $obj->title . '</title>';
        $ret. ='<author>' . $obj->author . '</author>';
        $ret. ='<date>' . $obj->date . '</date>';
        $ret. ='<category>' . $obj->category . '</category>';
        $ret. ='</article>';
        return $ret; }}Copy the code

JSONWriter:

class JSONWriter implements Writer {
    public function write(Article $obj) {
        $array = array('article'= >$obj);
        return json_encode($array); }}Copy the code

So each class is responsible for only one thing.

Step 4: Specific call

class Article {
    //...
    public function write(Writer $writer) {
        return $writer->write($this); }}Copy the code

In this case, the Article write method receives a concrete class that implements the Writer interface, and the article no longer needs to worry about the specific format. That is no longer its responsibility, but the Writer behind it can handle it.

How to pass a specific writer in depends on the context in which you are using it. For example, you can use a Factory class to do this:

class Factory {
    public static function getWriter() {// Get the request argument$format = $_REQUEST['format']; // Form the corresponding class name and check whether the class exists$class =  $format . 'Writer';
        if(class_exists($class)) {// Return a concrete instancereturn new $class(a); } // Throw a new Exception('Unsupported format'); }}Copy the code

Step 5: Terminal call

Suppose it ends up being called in controller like this:

$article = new Article('Polymorphism'.'Steve', time(), 0);
 
try {
    $writer = Factory::getWriter();
}
catch (Exception $e) {
    $writer = new XMLWriter();
}
 
echo $article->write($writer);
Copy the code

Depending on which framework you end up using, it’s actually a little simpler than that.

This is just one example of how polymorphism can be useful and necessary: Interface is a “blueprint” from which you can safely implement many forms of functionality to make your programs more modular and extensible.

At the end of the day, maybe we were more focused on how to better address interfaces in Laravel, how to use interfaces to make multi-team development more efficient, how to make it easier for us to respond to changing functional requirements, and so on. About these, we will continue to explore in depth in the course of “Laravel Underlying Core Technology Practical Revelations”.