You cannot interact with an interface except for accessing any defined constants in it or using it for TypeHints. Interfaces do not have method bodys. They are solely meant to define a contract implementing classes must obey.
interface Logger
{
const FOO = 1;
public function log($msg);
}
echo Logger::FOO; // 1
Logger::log($msg); // Fatal error: Cannot call abstract method Logger::log()
new Logger; // Fatal error: Cannot instantiate interface Logger
See http://de3.php.net/manual/en/language.oop5.interfaces.php
What is generally meant when coding against an interface or interacting with an interface is basically nothing more than calling methods defined in an interface in the classes implementing them. You call the implementation, not the definition. The definition just specifies that for every Class implementing the interface, there has to be a specific method with the specified arguments.
Consider these classes:
Class DbLog implements Logger
{
public function log($msg) { /* log $msg to database */ }
}
Class FileLog implements Logger
{
public function log($msg) { /* log $msg to file */ }
}
Both classes implement Logger
and therefor have to have a method log($msg)
. You're basically saying: "hey class, if you want be a Logger, make sure I can call log() on you.". Now somewhere in your code you might have a class that needs a logger, like
class Foo
{
protected $logger;
public function __construct(Logger $logger)
{
$this->logger = $logger;
$this->logger->log('I can haz logger! Yay!');
}
}
Foo
doesn't care if it gets FileLog
, DbLog
or any other concrete Logger. It just cares that it gets any Logger it can call log()
on. Foo isn't even interested in what log()
does. All Foo
cares about is being able to call log()
. You're not calling log()
in the interface though. You are calling it in the conrete class that was passed to Foo
, but in an UML diagram you'd represent this like it's shown in the page you linked, because you just coded against an interface.
The main advantage of this is that your classes are much less coupled. You can more easily swap out dependencies, for instance when using Mocks in unit-testing, and your code will be more maintainable.
Basically, think of an interface as a conceptual standardization. For instance, when you buy a new DVD Player, you expect it to have a ► button that somehow (you don't care how, just that) makes the player play the DVD. When you press that button, you're not pressing the general abstract DVD interface specification that says a DVD player must have a play button, but you clicked the concrete implementation of a play button on this brand of player.