#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.