
Originally Posted by
stereofrog
If you let me draw an analogy with natural language, classes are nouns and interfaces are adjectives. Nouns can be abstract ("animal") or concrete ("dog"), but they're still nouns -- they denote Things, while interfaces stand for Properties of Things.
To extend on this for the OP...forgiving the contrived example...lets say you had three classes - BedroomDoor, Gate and GarageDoor. Lets also imagine the BedroomDoor and GarageDoor (and all other Doors) have a range of varying behaviour, but both have exactly the same locking mechanisms. So we have:
PHP Code:
class Gate {
// gate specific behaviour
}
class BedroomDoor {
// bedroom door specific behaviour
public function lock($key) {
$this->lock->insert_key($key);
$key->turn('clockwise');
}
}
class GarageDoor {
// garage door specific behaviour
public function lock($key) {
$this->lock->insert_key($key);
$key->turn('clockwise');
}
}
Now, as you can see the two lock methods are exactly the same - duplication is evil!
In our imaginary contrived example, all Doors can be locked in the same way (but not Gates, these are bolted shut). We can eliminate this duplication by introducing an abstract class Door which implements this lock method for all of the concrete instances, eliminating the duplication.
PHP Code:
abstract class Door {
public function lock($key) {
$this->lock->insert_key($key);
$key->turn('clockwise');
}
}
class BedroomDoor extends Door {
// bedroom door specific behaviour
}
class GarageDoor extends Door {
// garage door specific behaviour
}
Note that we don't neccesarily have to use an abstract class to eliminate the duplication, we could just inherit from a normal concrete Door class that can be instantiated in its own right, depending on whether it makes sense for a Door to be instantiated on its own.
Now, interfaces - interfaces can be used to specify a specific set of behaviour and that behaviour's API which classes can implement. As explained above, interfaces are best looked at as adjectives. Both doors and gates can be opened. Thats an interface right there:
PHP Code:
interface Openable {
public function open() { }
}
Both doors (through the abstract Door class) and the gate can be opened, so they can implement the interface.
PHP Code:
class Gate implements Openable {
public function open() {
if($this->is_locked()) {
$this->unlock();
}
$this->leftSide()->pullOpen();
$this->rightSide()->pullOpen();
}
}
abstract class Door implements Openable {
// our abstract class defines the open function
// as abstract as we open different types of door
// differently
abstract public function open() {}
}
class GarageDoor {
public function open() { // implement here }
}
class BedroomDoor {
public function open() { // implement here }
}
By specifying that we will implement the Openable interface, the class is bound by that contract and you will get an error if you forget to implement any of the methods in the interface. Finally, you can take advantage of type hinting in your methods - lets say you need to pass an object into another class to do something - the receiving class doesn't care what object we pass it as long as it can be opened. We can enforce this using type hinting:
PHP Code:
class Foo {
public function openSomething(Openable $arg) {
$arg->open();
}
}
Doing the above ensures that whatever gets passed to the openSomething() method will respond to open() because it implements the Openable interface.
Interfaces/type hinting do not appeal to everybody and some people prefer duck typing which is favored heavily in dynamic languages like Ruby (which doesn't actually have interfaces or type hinting). The pros and cons of each are best discussed elsewhere though. 
HTH.
Bookmarks