Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the purpose of interfaces in php?

Tags:

php

interface

If I define an interface in PHP, and a factory class that creates an instance of that interface, is there any way I can force client code to only use the interface and not the underlying concrete class? From my understanding, the clients are able to actually use any public functions/fields in the underlying class as well.

Here is an example:

<?php
interface IMyInterface
{
    public function doSomething();
}
?>

<?php
class ConcreteImplOfMyInterface implements IMyInterface
{
    const NotPartOfInterface = 'youcantseeme';

    public function doSomething()
    {
    }
}
?>

<?php
class MyInterfaceFactory
{
    public static function createMyInterface()
    {
        return new ConcreteImplOfMyInterface(); 
    }
}
?>

<?php
function client()
{
    $myInterface = MyInterfaceFactory::createMyInterface();
    return $myInterface::NotPartOfInterface;
}
?>
like image 936
jameswelle Avatar asked Dec 07 '10 01:12

jameswelle


4 Answers

This is why interfaces are good in PHP:

interface Printable{
    public function display();
}

function display(Printable $obj){
    $obj->display();
}

It requires that any variable going into that function be an instance of Printable. Thus, you force anyone using your code to implement that interface if you want to use that function.

PHP 5.1 http://php.net/manual/en/language.oop5.typehinting.php

If you want to make sure someone else is not able to use specific methods or variables of a class, you need to define those methods and variables as private. This will make them unable to be used by anything but that specific class. (Not even classes that extend your class can use them)

like image 145
Tyler Carter Avatar answered Sep 23 '22 20:09

Tyler Carter


What you're asking for is only possible with a statically typed language, and since PHP is dynamically typed, the short answer is that it's not possible.

For example, in Java, createMyInterface could return an IMyInterface, and the only possible operations on this object are those defined in the interface itself. Of course, the object is really of type ConcreteImplOfMyInterface, so you can always cast it to that type to access the other fields/methods.

PHP has no declared types, so what you return from a function is simply a "variable" -- it has no type. And because there are no types, all field/method lookups are dynamic, so anything that is "there" in the object can always be accessed.

In a way, interfaces are indeed somewhat limited in use in a language such as PHP -- any class that implements an interface must implement all its methods, but since there is no guarantee as to what a function can return in the first place, there is essentially no guarantee of anything at all. The best you can do is to use instanceof to check whether an unknown variable implements a given interface.

like image 42
casablanca Avatar answered Sep 24 '22 20:09

casablanca


Since PHP is a dynamic language, it means all accesses to class members, etc. will be resolved at runtime. Which means if I have code that calls $foo->bar() and I got object in $foo that has method called bar() then it would be called even if it might be not the method bar() that I intended to call but some other method on some other object that by coincidence is named the same.

However, that being said, you can provide some protection by using typed parameters to have function accept only specific objects:

function doingSomething(IMyInterface $foo) {
  $foo->doSomething();
}

However, you still can not prohibit anyone from implementing IMyInterface and then writing functions that accept IMyInterface but use it as if it were object of some higher class. As I said, this is due to PHP being dynamic language.

like image 26
StasM Avatar answered Sep 24 '22 20:09

StasM


Make the methods private.

return $myInterface.NotPartOfInterface;

Does that work? I don't think it should. I think you want the :: operator.

. is only used for concatenating strings.

like image 31
alex Avatar answered Sep 24 '22 20:09

alex