Skip to content

Latest commit

 

History

History
142 lines (107 loc) · 3.78 KB

6.md

File metadata and controls

142 lines (107 loc) · 3.78 KB

#Lesson 6: Interfaces

##New Keywords:

  • interface
  • implements
  • scope resolution operator ::

Interfaces closely resemble abstract classes, but cannot contain concrete methods or properties. In order to create an interface, use the interface keyword.

<?php

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

You can then implement an interface with another class by using the implements keyword. Just as concrete classes can contain additional properties and methods to augment an abstract class, so to can they augment interfaces.

<?php

class Person implements IPerson {
  private $name;

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

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

  function __construct($name) {
    $this->setName($name);
  }

  function sayHi() {
    echo "Hi.\n";
  }
}

###Constants

You can't use variables inside of an interface, but you can use constants.

<?php

interface IDB {
  const HOST='example.com';
  const USER='root';
  const PASSWORD='root';
  const DB='allthedata';

  function connString();
}

Those constants can be accessed via the scope resolution operator :: inside of an implementing class. For example:

<?php

class SqlDb implements IDB {
  private $host = IDB::HOST;

  function connString() {
    echo $this->host;
  }
}

###Typing Data When a client class declares a method that uses an object, we can use type hinting to ensure that that the method is passed the correct object.

Given our previously defined IPerson interface, and Person concrete class, we can define a Client class that does something with a Person object, for example we can print their name.

It would be nice if we could ensure that the method in the client class that prints the name is passed a Person object. However, we want to type hint to say that we can use any object that implements the IPerson interface rather than limit it to a specific implementation of the interface.

When we type hint, we can specify an interface, and a instance of an implementing class will still pass the type hint. Consider the following:

<?php

class Client {
  function __construct() {
    $person = new Person();
    $this->printName($person);
  }

  function printName(IPerson $person) {
    echo $person->getName();
  }
}

In this example, even though we've passed a Person object to printName the and we've specified that printName should be passed an IPerson, the type hint passes because the Person object is from a class that implements the IPerson interface. In the case that we created another class, lets just say WeirdPerson, we could still pass an instance of that object to printName as well since so long as the WeirdPerson class implements the IPerson interface.

###Drupal Examples: Drupal's entities are a great place to look at interfaces. Inside of includes/entity.inc a DrupalEntityControllerInterface is defined.

This interface allows for a developer wishing to create a custom entity controller to do so simply by adhering to the interface.

Drupal's own default controller DrupalDefaultEntityController implements this interface and defines a bunch of concrete methods as well. For most developers, simply extending Drupal's DrupalDefaultEntityController is more than enough for creating custom entities, but for those using some sort of noSQL database, creating a custom controller is available, it just needs to implement the DrupalEntityControllerInterface interface.

##Exercise:

  • Create an interface to give a Person object from lesson 3 an email address and website.
  • Modify the concrete class from lesson 3 to implement your new interface.
  • Instantiate an object from the concrete class.
  • Set the email and website of the object, and then echo it back out.