PHP Classes and Objects Requiring Multiple Classes to Behave Similarly - Web Development and Design | Tutorial for Java, PHP, HTML, Javascript PHP Classes and Objects Requiring Multiple Classes to Behave Similarly - Web Development and Design | Tutorial for Java, PHP, HTML, Javascript

Breaking

Post Top Ad

Post Top Ad

Saturday, May 25, 2019

PHP Classes and Objects Requiring Multiple Classes to Behave Similarly

PHP Classes and Objects




Requiring Multiple Classes to Behave Similarly

Problem

You want multiple classes to use the same methods, but it doesn’t make sense for all the classes to inherit from a common parent class.

Solution

Define an interface and declare that your class will implement that interface:

          interface NameInterface {
                public function getName();
                public function setName($name);
          }

          class Book implements NameInterface {
                private $name;
  
                public function getName() {
                      return $this->name;
                }

                public function setName($name) {
                      return $this->name = $name;
                }
          }

The NameInterface interface defines two methods necessary to name an object. Because books are nameable, the Book class says it implements the NameInterface interface, and then defines the two methods in the class body.

When you want to include the code that implements the interface, define a trait and declare that your classes will use that trait:

          trait NameTrait {
                 private $name;

                 public function getName() {
                      return $this->name;
                 }

                 public function setName($name) {
                      return $this->name = $name;
                 }
          }

          class Book {
                 use NameTrait;
          }

          class Child {
                 use NameTrait;
          }

The NameTrait trait defines and implements two methods necessary to name an object. Because books are nameable, the Book class says it will use the NameTrait trait, and then you can call the two methods in the class body.

Discussion

In object-oriented programming, objects must work together. Therefore, you should be able to require a class (or more than one class) to implement methods that are necessary for the class to interact properly in your system.

For instance, an e-commerce application needs to know a certain set of information about every item up for sale. These items may be represented as different classes: Book, CD, DVD, etc. However, at the very minimum you need to know that every item in your catalog has a name, regardless of its type. (You probably also want them to have a price and maybe even an ID, while you’re at it.)

The mechanism for forcing classes to support the same set of methods is called an interface. Defining an interface is similar to defining a class:

          interface NameInterface {
                 public function getName();
                 public function setName($name);
          }

Instead of using the keyword class, an interface uses the keyword interface. Inside the interface, define your method prototypes, but don’t provide an implementation.

This creates an interface named NameInterface. Any class that has the NameInter face must implement the two methods listed in the interface: getName() and setName().

When a class supports all the methods in the interface, it’s said to implement the interface. You agree to implement an interface in your class definition:

          class Book implements NameInterface {
                 private $name;

                 public function getName() {
                      return $this->name;
                 }

                 public function setName($name) {
                      return $this->name = $name;
                 }
          }

Failing to implement all the methods listed in an interface, or implementing them with a different prototype, causes PHP to emit a fatal error.

A class can agree to implement as many interfaces as you want. For instance, you may want to have a ListenInterface interface that specifies how you can retrieve an audio clip for an item. In this case, the CD and DVD classes would also implement ListenInterface, whereas the Book class wouldn’t. (Unless, of course, it is an audio book.)

When you use interfaces, it’s important to declare your classes before you instantiate objects. Otherwise, when a class implements interfaces, PHP can sometimes become confused. To avoid breaking existing applications, this requirement is not enforced, but it’s best not to rely on this behavior.

To check if a class implements a specific interface, use class_implements(), as shown:

          class Book implements NameInterface {
                 // .. Code here
          }

          $interfaces = class_implements('Book');
          if (isset($interfaces['NameInterface'])) {
                 // Book implements NameInterface
          }

You can also use the Reflection classes:

          class Book implements NameInterface {
                 // .. Code here
          }

          $rc = new ReflectionClass('Book');
          if ($rc->implementsInterface('NameInterface')) {
                print "Book implements NameInterface\n";
          }

When you want to share code across two classes, use a trait:

          trait NameTrait {
                private $name;

                public function getName() {
                       return $this->name;
                }

                public function setName($name) {
                       return $this->name = $name;
                }
          }

          class Book {
                use NameTrait;
          }

          $book = new Book;
          $book->setName('PHP Cookbook');
          print $book->getName();

You can use interfaces and traits together. This is actually a best-practice design:

          class Book implements NameInterface {
                use NameTrait;
          }

Interfaces allow you to establish clear contracts with explicit promises about how your objects behave. Traits allow you to reuse code across objects that don’t have an “is a” inheritance relationship; they are just a programmatic way to avoid copy and pasting code in multiple places.

Interfaces combined with traits give you the best of both. The interface provides the contract across a wide set of classes, and the trait lets you fulfill it. Then, a specific class can choose to use the trait, or implement the interface on its own. For example, you could impose a contraint that each Book must have a unique name or that the name should be stored in a database. In these cases, the NameTrait wouldn’t serve your needs.

You can have a class implement multiple interfaces or traits by separating them with a comma:

          class Book implements NameInterface, SizeInterface {
                use NameTrait, SizeTrait;
          }


No comments:

Post a Comment

Post Top Ad