Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

interact with an interface?

Tags:

oop

php

from what i've read it seems that one can interact with an interface?

eg. lets say that i've got an interface with an empty method "eat()"

then 2 subclasses are implementing this interface.

can my controller interact with only the interface and use it's eat() method?

have a look at the picture in this link strategy

like image 502
never_had_a_name Avatar asked Apr 23 '10 09:04

never_had_a_name


1 Answers

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://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.

like image 74
Gordon Avatar answered Oct 03 '22 13:10

Gordon