类与对象
在线手册:中文 英文
PHP手册

接口

使用接口(interface),你可以指定某个类必须实现哪些方法,但不需要定义这些方法的具体内容。

我们可以通过interface来定义一个接口,就像定义一个标准的类一样,但其中定义所有的方法都是空的。

接口中定义的所有方法都必须是public,这是接口的特性。

实现

要实现一个接口,可以使用implements操作符。类中必须实现接口中定义的所有方法,否则 会报一个fatal错误。如果要实现多个接口,可以用逗号来分隔多个接口的名称。

Note:

实现多个接口时,接口中的方法不能有重名。

Note:

接口也可以继承,通过使用extends操作符。

常量

接口中也可以定义常量。接口常量和类常量的使用完全相同。 它们都是定值,不能被子类或子接口修改。

范例

Example #1 接口代码示例

<?php

// 声明一个'iTemplate'接口
interface iTemplate
{
    public function 
setVariable($name$var);
    public function 
getHtml($template);
}


// 实现接口
// 下面的写法是正确的
class Template implements iTemplate
{
    private 
$vars = array();
  
    public function 
setVariable($name$var)
    {
        
$this->vars[$name] = $var;
    }
  
    public function 
getHtml($template)
    {
        foreach(
$this->vars as $name => $value) {
            
$template str_replace('{' $name '}'$value$template);
        }
 
        return 
$template;
    }
}

// 下面的写法是错误的,会报错:
// Fatal error: Class BadTemplate contains 1 abstract methods
// and must therefore be declared abstract (iTemplate::getHtml)
class BadTemplate implements iTemplate
{
    private 
$vars = array();
  
    public function 
setVariable($name$var)
    {
        
$this->vars[$name] = $var;
    }
}
?>

Example #2 Extendable Interfaces

<?php
interface a
{
    public function 
foo();
}

interface 
extends a
{
    public function 
baz(Baz $baz);
}

// 正确写法
class implements b
{
    public function 
foo()
    {
    }

    public function 
baz(Baz $baz)
    {
    }
}

// 错误写法会导致一个fatal error
class implements b
{
    public function 
foo()
    {
    }

    public function 
baz(Foo $foo)
    {
    }
}
?>

Example #3 多个接口间的继承

<?php
interface a
{
    public function 
foo();
}

interface 
b
{
    public function 
bar();
}

interface 
extends ab
{
    public function 
baz();
}

class 
implements c
{
    public function 
foo()
    {
    }

    public function 
bar()
    {
    }

    public function 
baz()
    {
    }
}
?>

Example #4 使用接口常量

<?php
interface a
{
    const 
'Interface constant';
}

// 输出接口常量
echo a::b;

// 错误写法,因为常量的值不能被修改。接口常量的概念和类常量是一样的。
class implements a
{
    const 
'Class constant';
}
?>

你也可以看看instanceof关键字的文档。


类与对象
在线手册:中文 英文
PHP手册
PHP手册 - N: 接口

用户评论:

treii28 at gmail dot com (05-Apr-2012 06:02)

I just learned that you can cast a function using an abstract interface definition rather than referring to a specific class that implements it.  e.g.:

interface myInterface
{
  public function someFunction();
}
class myClassA implements myInterface
{
  public function someFunction() {
    // does something
  }
}

class myClassB
{
  public function castFunction(myInterface $obj) {
    // do something with object
  }
}

This will be VERY useful for abstraction as I don't have to name specific implementations of an interface, but can instead just use the interface to verify whatever object it is that is being passed in still has expected functionality.
My question now is, is there any way you can cast using multiple interfaces?

md2perpe (04-Apr-2012 11:08)

When implementing an interface that extends Traversable, not only you have to supply an implementation of Traversable (i.e. either Iterator or IteratorAggregate) and tell which one you implement.

It also matters in which order the implemented interfaces are listed.

Changing "implements Iterator, MyTraversable" to "implements MyTraversable, Iterator" in the following snippet fails as of PHP 5.3.10:

<?php
interface MyTraversable extends Traversable {}

class
MyClass implements Iterator, MyTraversable
{
   
// Implement Iterator
   
public function rewind() {}
    public function
valid() {}
    public function
current() {}
    public function
key() {}
    public function
next() {}
}
?>

guillaume at metayer dot ca (09-Mar-2012 11:11)

I think good OOP design will actually require both what dlovell2001 and anon said. In the examples below, if Database is only an abstract class, you will have limitations. What if one day you have a special Database object that is so different for some specific needs, that it should NOT inherit from the Database abstract class? You would be stuck. In my opinion, the best thing to do would be to have a Database abstract class that implements a DatabaseInterface interface.

When working on a Database object, you would first make sure it implements the DatabaseInterface object (dlovell2001, this is something very important that's missing in your example). You can still use any object inheriting the Database class (because this class implements the DatabaseInterface interface) but you are NOT limited to using an object inheriting from Database. Any object implementing the DatabaseInterface will do. This way, you are not limited to a specific type.

Interfaces are a good way to have a 'contract' with the component using a certain object, without being limited to using a specific type for that object. Also remember to use the 'instanceof' or similar when working on such object. One goal of interfaces is to actually enforce the signature of an object before actually working with it.

anon (01-Mar-2012 11:13)

dlovell2001's example does not quite get it right either. Both interfaces and classes provide abstraction. His example would be better implemented as an abstract class than an interface.

The distinction between the two is that an abstract class says what an object is and describes its visible appearance. An interface describes the visible appearance without restricting what the object may be.

Whether the Database is an SQL database, an Oracle database, or some other type of database, it is still a database - a particular kind of object. In this case, the description should be an abstract class - class because it is a database, abstract because the class is useless without knowing just what kind of database it is.

On the other hand, consider the iterator. The object may be an array, a json string, a filesystem directory tree, a database result set, the infinite set of prime numbers, a random number generator, etc. While these are all different objects, they share in common the fact that they have a first value and that each value will be followed by another until a last value is reached, if ever. These are all different types of objects, so different classes, but share a common way of accessing these values. This is where you use an interface.

Use abstract classes to declare the common method signatures of related classes. Use interfaces to declare the common method signatures of unrelated classes.

And while we are here, once you have 5.4, use parent classes to define the common methods and properties of related classes and traits to define the common methods and properties of unrelated classes.

dlovell2001 at yahoo dot com (04-Feb-2012 06:40)

It seems like many contributors are missing the point of using an INTERFACE. An INTERFACE is not specifically provided for abstraction. That's what a CLASS is used for. Most examples in this article of interfaces could be achieved just as easily using just classes alone.

An INTERFACE is provided so you can describe a set of functions and then hide the final implementation of those functions in an implementing class. This allows you to change the IMPLEMENTATION of those functions without changing how you use it.

For example: I have a database. I want to write a class that accesses the data in my database. I define an interface like this:

interface Database {
function listOrders();
function addOrder();
function removeOrder();
...
}

Then let's say we start out using a MySQL database. So we write a class to access the MySQL database:

class MySqlDatabase implements Database {
function listOrders() {...
}
we write these methods as needed to get to the MySQL database tables. Then you can write your controller to use the interface as such:

$database = new MySqlDatabase();
foreach ($database->listOrders() as $order) {

Then let's say we decide to migrate to an Oracle database. We could write another class to get to the Oracle database as such:

class OracleDatabase implements Database {
public function listOrders() {...
}

Then - to switch our application to use the Oracle database instead of the MySQL database we only have to change ONE LINE of code:

$database = new OracleDatabase();

all other lines of code, such as:

foreach ($database->listOrders() as $order) {

will remain unchanged. The point is - the INTERFACE describes the methods that we need to access our database. It does NOT describe in any way HOW we achieve that. That's what the IMPLEMENTing class does. We can IMPLEMENT this interface as many times as we need in as many different ways as we need. We can then switch between implementations of the interface without impact to our code because the interface defines how we will use it regardless of how it actually works.

julien arobase fastre point info (12-Dec-2011 07:12)

If you use namespaces and autoloading, do not forget to mention the use statement for each class used in yours arguments, before your class:

<?php
#file : fruit/squeezable.php
namespace fruit
use Bar\Foo;

interface
squeezable {
  public function
squeeze (Foo $foo);
}
?>

<?php
#file: orange

namespace fruit\citrus;

class
orange {
  public function
squeeze(Foo $foo);
}
#Will throw an exception Fatal error: Declaration of "fruit\citrus\orange::squeeze must be compatible with that of fruit\squeezable() in fruit/squeezable.php
?>

<?php
#file: orange

namespace fruit\citrus;
use
Bar\Foo; #DO NOT FORGET THIS!

class orange {
  public function
squeeze (Foo $foo);
}
#Will be correct
?>

FX Laviron (25-Oct-2011 05:12)

The error "Can't inherit abstract function IB::f() (previously declared abstract in IA)" in the following code
<?php

interface IA {     public function f(); }

interface
IB {     public function f(); }

class
Test implements IA, IB {
    public  function
f() {
        echo
"f";
    }
}
$o = new Test();
$o->f();
?>

can be avoided (if appropriate) by adding a ancestor interface to IA and IB, and moving the common method to it:

<?php

interface IAncestor {     public function f(); }

interface
IA {   }

interface
IB extends IAncestor {   }

class
Test implements IA, IB {
    public  function
f() {
        echo
"f";
    }
}
$o = new Test();
$o->f();
?>

thanhn2001 at gmail dot com (03-Mar-2011 09:37)

PHP prevents interface a contant to be overridden by a class/interface that DIRECTLY inherits it.  However, further inheritance allows it.  That means that interface constants are not final as mentioned in a previous comment.  Is this a bug or a feature?

<?php

interface a
{
    const
b = 'Interface constant';
}

// Prints: Interface constant
echo a::b;

class
b implements a
{
}

// This works!!!
class c extends b
{
    const
b = 'Class constant';
}

echo
c::b;
?>

jballard at natoga dot com (06-Jan-2011 09:33)

If it isn't already obvious, you can create an object of a class above the class declaration if it does NOT implement an interface. However, when a class DOES implement an interface, PHP will throw a "class not found" error unless the instantiation declaration is _below_ the class definition.

<?php
$bar
= new foo(); // Valid

class foo
{
   
}
?>

<?php
$bar
= new foo(); // Invalid - throws fatal error

interface foo2
{

}

class
bar implements foo2
{
   
}

$bar = new foo(); // Valid, since it is below the class declaration

?>

Also, @Jeffrey -- Lol? What? Is that a joke? PHP interfaces have nothing to do with connecting to "peripheral devices" or "cameras", etc. Not even in the least sense. This is a very common miscommunication with the word "interface", as interfaces in programming are not at all like interfaces in electronics or drivers, etc.

gratcypalma at gmail dot com (19-Nov-2010 07:07)

here is my simply method muliple inheritence with __construct function..
<?php
class foo {
    protected
$mam = 'mamam';
    function
__construct() {
        echo
'foo';
    }
}
class
bar extends foo {
    function
__construct() {
       
parent:: __construct();
        echo
'bar';
    }
}
class
foobar extends bar {
    function
__construct() {
       
parent:: __construct();
        echo
'foobar';
    }
}

$foo = new foobar();
?>

Anonymous (13-Aug-2010 08:44)

If you want to ensure implementation classes are correctly initialised (i.e. due to trickery one needs to do to work around lack of multiple inheritance), simply add  __construct() to your interface, so risk of init being forgotten is reduced.

drieick at hotmail dot com (23-Feb-2010 05:29)

I was wondering if implementing interfaces will take into account inheritance. That is, can inherited methods be used to follow an interface's structure?

<?php

interface Auxiliary_Platform {
    public function
Weapon();
    public function
Health();
    public function
Shields();
}

class
T805 implements Auxiliary_Platform {
    public function
Weapon() {
       
var_dump(__CLASS__);
    }
    public function
Health() {
       
var_dump(__CLASS__ . "::" . __FUNCTION__);
    }
    public function
Shields() {
       
var_dump(__CLASS__ . "->" . __FUNCTION__);
    }
}

class
T806 extends T805 implements Auxiliary_Platform {
    public function
Weapon() {
       
var_dump(__CLASS__);
    }
    public function
Shields() {
       
var_dump(__CLASS__ . "->" . __FUNCTION__);
    }
}

$T805 = new T805();
$T805->Weapon();
$T805->Health();
$T805->Shields();

echo
"<hr />";

$T806 = new T806();
$T806->Weapon();
$T806->Health();
$T806->Shields();

/* Output:
string(4) "T805"
string(12) "T805::Health"
string(13) "T805->Shields"
<hr />string(4) "T806"
string(12) "T805::Health"
string(13) "T806->Shields"
*/

?>

Class T805 implements the interface Auxiliary_Platform. T806 does the same thing, but the method Health() is inherited from T805 (not the exact case, but you get the idea). PHP seems to be fine with this and everything still works fine. Do note that the rules for class inheritance doesn't change in this scenario.

If the code were to be the same, but instead T805 (or T806) DOES NOT implement Auxiliary_Platform, then it'll still work. Since T805 already follows the interface, everything that inherits T805 will also be valid. I would be careful about that. Personally, I don't consider this a bug.

This seems to work in PHP5.2.9-2, PHP5.3 and PHP5.3.1 (my current versions).

We could also do the opposite:

<?php

class T805 {
    public function
Weapon() {
       
var_dump(__CLASS__);
    }
}

class
T806 extends T805 implements Auxiliary_Platform {
    public function
Health() {
       
var_dump(__CLASS__ . "::" . __FUNCTION__);
    }
    public function
Shields() {
       
var_dump(__CLASS__ . "->" . __FUNCTION__);
    }
}

$T805 = new T805();
$T805->Weapon();

echo
"<hr />";

$T806 = new T806();
$T806->Weapon();
$T806->Health();
$T806->Shields();

/* Output:
string(4) "T805"
<hr />string(4) "T805"
string(12) "T806::Health"
string(13) "T806->Shields"
*/

?>

This works as well, but the output is different. I'd be careful with this.

uramihsayibok, gmail, com (10-Feb-2010 07:25)

Interfaces can define static methods, but note that this won't make sense as you'll be using the class name and not polymorphism.

...Unless you have PHP 5.3 which supports late static binding:

<?php

interface IDoSomething {
    public static function
doSomething();
}

class
One implements IDoSomething {
    public static function
doSomething() {
        echo
"One is doing something\n";
    }
}

class
Two extends One {
    public static function
doSomething() {
        echo
"Two is doing something\n";
    }
}

function
example(IDoSomething $doer) {
   
$doer::doSomething(); // "unexpected ::" in PHP 5.2
}

example(new One()); // One is doing something
example(new Two()); // Two is doing something

?>

If you have PHP 5.2 you can still declare static methods in interfaces. While you won't be able to call them via LSB, the "implements IDoSomething" can serve as a hint/reminder to other developers by saying "this class has a ::doSomething() method".
Besides, you'll be upgrading to 5.3 soon, right? Right?

(Heh. I just realized: "I do something". Unintentional, I swear!)

btjakachira at gmail dot com (11-Jan-2010 09:52)

I'm going to give a very simple explanation between interface and any abstract. I'm not going to repeat basic stuff mentioned above e.g you can not instantiate an interface or an abstract. Any class with an abstract method should be declared as abstract.. etc.

Example.
I will show you where and when to use interfaces. Normally people will use interface when absctracting becomes a problem. Lets say we start with the following objects

<?php

Person

Employee
Employer
Criminal
Rapist
President
Student
?>

You will easily see that Employee is a Person, Criminal is a person etc.. Therefore we can have Person as a PARENT class. For person to be abstract, you decide within your application if a person object makes sense... if it doesn't make the person an abstract so that you wont have alien objects.

Now, interfaces are used when, in a group of objects, you have two or more objects that share similar behaviour. E.g President and Employer will makePolicy() while Criminal and Rapist will commitCrime(). Having said that, normally people would put these methods in their respective classes (but defeating the OO designs). If you put makePolicy() in President and Employer class there will be duplication of code. Other people can be tempted to put thet makePolicy() and commitCrime() in Person as abstract methods so that the 6 objects will see the methods. Its not a good idea as Student or Employee will not normally makePolicy() or commitCrime(). In fact, it means Employee object can makePolicy() of increasind salary :-) . Therefore in this case we use INTERFACES

<?php
 
interface HighOffice {
   public function
makePolicy();
   public function
declareEmergency();
}

 interface
jailable {
   public function
commitCrime();
   public function
appeal();
}

abstract class
Person {
  public function
getAge()
  {
    return
"28years";
  }
}

public class
Employee extend Person {
 
//do stuff for employee
}

public class
Criminal extend Person impliments jailable{
 
//do stuff for a criminal.
 
 //these must be present.
 
public function commitCrime()
  {

  }
  public function
appeal()
  {
  }

public class
President extend Person impliments HighOffice
{

 
//do other stuff for President

  //then a President should make policies and declare emergency
  
public function makePolicy()
   {
    }
   public function
declareEmergency()
  {
  }
}

}
 
?>

NB: forgive me for errors syntax. I in the middle of doing Java.

You have noticed that relevant behavious have been added to the relevant objects..

rskret at ranphilit dot com (02-Jun-2009 10:47)

This may help understand EX.2. Below are modifiers and additions to
the code. Refer to EX.2 to make a complete code block(this saves comment
space!).
I found the function definition baz(Baz $baz) baffling. Lucky was
able to sus it out fast. Seems method baz requires just one arg and
that must be an instance of the class Baz. Here is a way to know how to
deal with that sort of arg...
<?php
# modify iface b...adding $num to get better understanding
interface b extends a
{
    public function
baz(Baz $baz,$num);
}
# mod claas c
class c implements b
{
    public function
foo()
    {
        echo
'foo from class c';
    }
    public function
baz(Baz $baz,$num)
    {
       
var_dump ($baz);# object(Baz)#2 (1) { ["bb"]=>  string(3) "hot" }
       
echo '<br>';
        echo
$baz->bb." $num";echo '<br>';# hot 6
   
}
}
# add a class Baz...
class Baz
{
    public
$bb='hot';
    function
ebaz(){   
        echo
'this is BAZ';
    }
}
# set instance of Baz and get some output...
$bazI=new Baz;
baz::ebaz();echo '<br>';# this is BAZ
c::baz($bazI,6);
?>

cretz (21-Sep-2008 11:49)

FYI, interfaces can define constructors, destructors, and magic methods. This can be very helpful especially in the case of constructors when instantiating an implementing class via reflection in some sort of factory. Of course, it is not recommended to do such a thing since it goes against the nature of a true interface.

lazybones_senior (15-Sep-2008 06:41)

WHOA! KEEP IT SIMPLE...

With the code below, you already get a feel at how much ground this app might cover.

<?php

interface ElectricalDevice{
  public function
power_on();
  public function
power_off();
}

interface
FrequencyTuner{
  public function
get_frequencey();
  public function
set_frequency($f);
}

class
ElectricFan implements ElectricalDevice{
 
// define ElectricalDevice...
}

class
MicrowaveOven implements ElectricalDevice{
 
// define ElectricalDevice...
}

class
StereoReceiver implements ElectricalDevice, FrequencyTuner{
 
// define ElectricalDevice...
  // define FrequencyTuner...
}

class
CellPhone implements ElectricalDevice, FrequencyTuner{
 
// define ElectricalDevice...
  // define FrequencyTuner...
}

?>

Even those who lack imagination can fill in the blanks from here.

secure_admin (14-Sep-2008 10:28)

In response to harryjry and mehea concerning your Weather Model. The problem is that you don't need all the things you think you need. In OOP, good class definitions get to the point rather quickly.

<?php
class Weather{
  public
$time, $temperature, $humidity;

  public function
__construct($tm, $t, $h){
   
$this->time = $tm;
   
$this->temperature = $t;
   
$this->humidity = $h;
  }

  public function
__toString(){
    return
"Time: $this->time,
      Temperature:
$this->temperature&deg;,
      Humidity:
$this->humidity%";
  }
}

$forecasts = array(
  new
Weather("1:00 pm", 65, 42),
  new
Weather("2:00 pm", 66, 40),
  new
Weather("3:00 pm", 68, 39)
 
// add more weather reports as desired...
);
echo
"Forecast for Chicago, IL:<br>";
foreach(
$forecasts as $forecast) echo ' - ' . $forecast '<br>';
?>
Forecast for Chicago, IL:
- Time: 1:00 pm, Temperature: 65°, Humidity: 42%
- Time: 2:00 pm, Temperature: 66°, Humidity: 40%
- Time: 3:00 pm, Temperature: 68°, Humidity: 39%

Note: MySQL can store data like this already, but if you included constants, more variables, and other functions in the Weather class, then maybe, just maybe it could be of use.

mehea (30-Jul-2008 07:55)

While a subclass may implement an interface by extending an abstract class that implements the interface, I question whether it is good design to to do so.  Here's what I would suggest while taking the liberty of modifying the above weather/wet model:

<?php
interface water
{
    public function
makeItWet();
}

 
/**
   * abstract class implements water but defines makeItWet
   * in the most general way to allow child class to
   * provide specificity
**/
abstract class weather implements water                   
{
   private
$cloudy;
   public function
makeItWet(){}
   abstract public function
start();
   abstract public function
getCloudy();
   abstract public function
setCloudy();
}

class
rain extends weather                            {
    private
$cloudy;   
    public function
start() {
        return
"Here's some weather. ";
    }
   
    public function
makeItWet() {
        return
'it is raining cats and dogs today.';
    }
    public function
getCloudy() {
        return
$this->cloudy;
    }
    public function
setCloudy($bln=false) {
       
$this->cloudy = $bln;
    }
}

$a = new rain();
echo
$a->start();
$a->setCloudy(true);
if (
$a->getCloudy()) {
    echo
'It is a cloudy day and ';
}
echo
$a->makeItWet();

?>

logik at centrum dot cz (17-Jul-2008 10:17)

Makes them useles a bit. I give an example:
I have a class that enumerate (so implements iterator) a interface that has method key() that returns key for the enumerated object.
I cannot implement iterator, that enumerates the objects by itself (so current() returns this), because of collision of method key(). But it's not collision - the key in the iterator and the key in the enumerated object has the same meaning and allways returns same values.
(Common example of this iterator is iterator, that reads from database - make a special object for each row is waste of time).

Yes - there are workarounds - e.g. rewrite the code so current don't return this - but it's in some cases waste of processor time.
Or I can rename the method key in enumerated object - but why should I wrote the same method twice? It's either waste of time (if the function key is simply duplicated) or waste of time (if the renamed key calls original key).
Well, the right, clear way there would be to redefine interface iterator -- move the method key to the ancestor of iterator, and makes the ancestor ancestor of enumerated interface too. But it's (with built-in interfaces) impossible too.

harryjry at yahoo dot com (10-Jun-2008 10:29)

The structure I am working with has a lot of inheritance going on, but not all methods are specified in one place. I needed a way to make sure an interface would be used, but that the method(s) defined in the interface are defined somewhere.

As such, I learned that the parent can define the interface's methods, and then the children can override that method at will without having to worry about the interface.

To expand on nrg1981's example, the following is possible:

<?php
interface water
{
    public function
makeItWet();
}

class
weather
{
    public function
makeItWet()
    {
        return
'it may or may not be wet';
    }
   
    public function
start()
    {
        return
'Here is some weather';
    }
}

class
rain extends weather implements water
{
    public function
makeItWet()
    {
        return
'It is wet';
    }
}

class
thunder extends weather implements water
{

}

$a = new rain();
echo
$a->start() . "\n";
echo
$a->makeItWet() . "\n";

$a = new thunder();
echo
$a->start() . "\n";
echo
$a->makeItWet() . "\n";

?>

kaisershahid at gmail dot com (07-Apr-2008 01:41)

php at wallbash dot com's comment of "It's important to note this because it is very unexpected behavior and renders many common Interface completly useless" doesn't make sense.

the idea of the interface is to force objects that aren't related to be reused in a common way. without them, to force that requirement, all objects that need those methods implemented would have to be descended from a base class that's known to have those methods. that's clearly not a smart idea if these objects aren't actually related.

one example (that i'm currently working on) is a background service that pulls information down from different content providers. i have a transport and i have an import. for both, what actually happens in the background is different from provider to provider, but since i'm implementing a transport & import interface, i only need to write code once, because i know exactly the what methods will be implemented to get the job done. then, i just have a config file that loads the class dynamically. i don't need something like

if ( $provider == "some company" )
{
   // use this set of code
}
elseif ( $provider == "another company" )
{
   // use this other set of code
}

instead, i can do:

foreach ( $providers as $provider => $info )
{
    $_transport = $info['transportObject'];
    $transport = new $_transport();
    $_import = $info['importObject'];
    $import = new $_import();
   
    $transport->setImporter( $import );
    $transport->retrieve();
}

it is expected behavior that when a class implements two interfaces that share one or more method names, an error is thrown, because interfaces don't relate to each other. if you want that sort of inferred behavior (i.e. A and B are different except for these shared methods), stick to [abstract] classes.

it sucks that interface methods might collide for some common types of tasks (get(), set(), etc.), so knowing that, design your interfaces with more unique method names.

michael dot martinek at gmail dot com (04-Jan-2008 04:18)

In regards to what Hayley Watson is writing:

The "interface" is a method of enforcing that anyone who implements it must include all the functions declared in the interface. This is an abstraction method, since you cannot just declare a base class and do something like "public abstract function myTest();" and later on extend that class.

If you don't override the default value in a parameter list, it's assumed that the default value was received by time you have any control to read or relay the value on again. There should be no problem in having all or none of your parameters in an interface having a default value, as the value is "auto-filled" if not explicitly provided.

I just came across interfaces in PHP.. but I use them quite a bit in Java and Delphi. Currently building different DB wrappers, but all must enforce common access using a base class.. and also enforce that all of specific routines are implemented.

Docey (11-Nov-2007 11:23)

Another note about default values in interfaces is that an class must implement at least the arguments as in the interface. that is: an implementation may have more arguments but not less if these additional arguments have an default value and thus can be called as declared in the interface.

an litte example:
<?php
interface myInterface{
  public function
setStuff($id, $name);
}

class
MyFirstClass implements myInterface{
  public function
setStuff($id, $name);
}

class
MySecondClass implements myInterface{
 public function
setStuff($id, $name, $type);
}

class
myThirdClass implements myInterface{
 public function
setStuff($id, $name, $type=0);
}
?>

Here mySecondClass will print an fatal error while myThirdClass is just fine because myThirdClass::setStuff($id, $name); is valid and thus fullfills the interface requirements. an interface declares as set of requirement on how methods can be called and any class implementing an interface thus agrees that is will provide these methods and that they can be called as in the interface. adding additional arguments with default values is thus allowed because it does not violate the agreement that the method can be called as in the interface.

nrg1981 {AT} hotmail {DOT} com (05-Oct-2007 02:48)

In case you would want to, a child class can implement an interface:

<?php

interface water
{
    public function
makeItWet();
}

class
weather
{
    public function
start()
    {
        return
'Here is some weather';
    }
}

class
rain extends weather implements water
{
    public function
makeItWet()
    {
        return
'It is wet';
    }
}

$a = new rain();
echo
$a->start();
echo
$a->makeItWet();

?>

Hayley Watson (21-Sep-2007 11:42)

If it's not already obvious, it's worth noticing that the parameters in the interface's method declaration do not have to have the same names as those in any of its implementations.

More significantly, default argument values may be supplied for interface method parameters, and they have to be if you want to use default argument values in the implemented classes:

<?php
interface isStuffable
{
    public function
getStuffed($ratio=0.5);
}

class
Turkey implements isStuffable
{
    public function
getStuffed($stuffing=1)
    {
       
// ....
   
}
}
?>

Note that not only do the parameters have different names ($ratio and $stuffing), but their default values are free to be different as well. There doesn't seem to be any purpose to the interface's default argument value except as a dummy placeholder to show that there is a default (a class implementing isStuffable will not be able to implement methods with the signatures getStuffed(), getStuffed($a), or getStuffed($a,$b)).

Hayley Watson (21-Sep-2007 06:34)

On an incidental note, it is not necessary for the implementation of an interface method to use the same variable names for its parameters that were used in the interface declaration.

More significantly, your interface method declarations can include default argument values. If you do, you must specify their implementations with default arguments, too. Just like the parameter names, the default argument values do not need to be the same. In fact, there doesn't seem to be any functionality to the one in the interface declaration at all beyond the fact that it is there.

<?php
interface isStuffed {
    public function
getStuff($something=17);
}

class
oof implements isStuffed {
    public function
getStuff($a=42) {
        return
$a;
    }
}

$oof = new oof;

echo
$oof->getStuff();
?>

Implementations that try to declare the method as getStuff(), getStuff($a), or getStuff($a,$b) will all trigger a fatal error.

php at wallbash dot com (05-Sep-2007 03:39)

Please note that the sentence "Note: A class cannot implement two interfaces that share function names, since it would cause ambiguity." _really_ means that it is not possible to do something like:

<?php

interface IA {
    public function
a();
}

interface
IB {
    public function
a();
}

class
Test implements IA, IB {
    public  function
a() {
        echo
"a";
    }
}
$o = new Test();
$o->a();
?>

lead to:
PHP Fatal error:  Can't inherit abstract function IB::a() (previously declared abstract in IA)

It's important to note this because it is very unexpected behavior and renders many common Interface completly useless.

zedd at fadingtwilight dot net (05-Jul-2007 05:42)

Regarding my previous note (04-Jul-2007 9:01):

I noticed a minor but critical mistake in my explanation. After the link to the PHP manual page on class abstraction, I stated:

"So by definition, you may only overload non-abstract methods."

This is incorrect. This should read:

"So by definition, you may only override non-abstract methods."

Sorry for any confusion.

zedd at fadingtwilight dot net (05-Jul-2007 05:01)

prometheus at php-sparcle:

Your code fails because you're effectively trying to do this:

<?php
   
abstract class IFoo
   
{
        abstract public function
Foo();
    }
   
    abstract class
IBar extends IFoo
   
{
       
// Fails; abstract method IFoo::Foo() must be defined in child and must match parent's definition
       
abstract public function Foo($bar);
    }
?>

By definition, all methods in an interface are abstract. So the above code segment is equivalent to your interface definitions and results in the same error. Why? Let's have a look at the PHP manual. From the second paragraph on class abstraction:

"When inheriting from an abstract class, all methods marked abstract in the parent's class declaration must be defined by the child;"

http://www.php.net/manual/en/language.oop5.abstract.php

So by definition, you may only overload non-abstract methods.

For example:

<?php
   
abstract class IFoo
   
{
        public function
Foo()
        {
           
// do something...
       
}
    }
   
    abstract class
IBar extends IFoo
   
{     
        public function
Foo($bar)
        {
           
// do something else...
       
}
    }
?>

This can't be directly replicated with interfaces since you can't implement methods inside of an interface. They can only be implemented in a class or an abstract class.

If you must use interfaces, the following accomplishes the same thing, but with two separate method names:

<?php
   
interface IFoo
   
{
        public function
Foo();
    }
   
    interface
IBar extends IFoo
   
{
        public function
Bar($bar);
    }
   
    class
FooBar implements IBar
   
{
        public function
Foo()
        {
           
// do something...
       
}
       
        public function
Bar($bar)
        {
           
// do something else...
       
}
    }
?>

If both methods need the same name, then you'll have to use non-abstract methods. In this case, interfaces aren't the right tool for the job. You'll want to use abstract classes (or just regular classes).

Maikel (12-Jan-2007 11:07)

if you want to implement an interface and in addition to use inheritance, first it uses “extends” and then “implements” example:

<?php
class MyChildClass extends MyParentClass implements MyInterface
{
  
// definition
}
?>

Chris AT w3style DOT co.uk (07-Dec-2006 01:25)

Note that you can extend interfaces with other interfaces since under-the-hood they are just abstract classes:

<?php

interface Foo {
    public function
doFoo();
}

interface
Bar extends Foo {
    public function
doBar();
}

class
Zip implements Bar {
    public function
doFoo() {
        echo
"Foo";
    }
    public function
doBar() {
        echo
"Bar";
    }
}

$zip = new Zip();
$zip->doFoo();
$zip->doBar();

?>

This is quite useful when you're using interfaces for identity more than the rigidity it places upon an API.  You can get the same result by implementing multiple interfaces.

An example of where I've used this in the past is with EventListener objects ala Java's Swing UI.  Some listeners are effectively the same thing but happen at different times therefore we can keep the same API but change the naming for clarity.

marasek AT telton POINT de (07-Sep-2006 02:01)

What is not mentioned in the manual is that you can use "self" to force object hinting on a method of the implementing class:

Consider the following interface:
<?php
interface Comparable
{function compare(self $compare);}
?>

Which is then implemented:

<?php

class String implements Comparable
{
    private
$string;
    function
__construct($string)
    {
$this->string = $string;}
    function
compare(self $compare)
    {return
$this->string == $compare->string;}
}

class
Integer implements Comparable
{
    private
$integer;
    function
__construct($int)
    {
$this->integer = $int;}
    function
compare(self $compare)
    {return
$this->integer == $compare->integer;}
}

?>

Comparing Integer with String will result in a fatal error, as it is not an instance of the same class:

<?php
$first_int
= new Integer(3);
$second_int = new Integer(3);
$first_string = new String("foo");
$second_string = new String("bar");

var_dump($first_int->compare($second_int)); // bool(true)
var_dump($first_string->compare($second_string)); // bool(false)
var_dump($first_string->compare($second_int)); // Fatal Error
?>

vbolshov at rbc dot ru (10-Aug-2006 10:34)

Consider the following:
[vbolshov@localhost tmp]$ cat t.php
<?php

error_reporting
(E_ALL | E_STRICT);

interface
i {
        function
f($arg);
}
class
c implements i {
        function
f($arg, $arg2 = null)
        {
        }
}
?>
[vbolshov@localhost tmp]$ php t.php
[vbolshov@localhost tmp]$

PHP doesn't generate a Fatal Error in this case, although the method declaration in the class differs from that in the interface. This situation doesn't seem good to me: I'd prefer classes being strictly bound to their interfaces.

spiritus.canis at gmail dot com (25-Oct-2005 06:45)

Regarding the example by cyrille.berliat:

This is not a problem and is consistent with other languages.  You'd just want to use inheritance like so:

<?php

class AbstractClass {
   public function
__ToString ( ) { return 'Here I am'; }
}

class
DescendantClass extends AbstractClass {}

interface
MyInterface {
   public function
Hello ( AbstractClass $obj );
}

class
MyClassOne implements MyInterface {

   public function
Hello ( AbstractClass $obj ) {
       echo
$obj;
   }
}
// Will work as Interface Satisfied

$myDC = new DescendantClass() ;
MyClassOne::Hello( $myDC ) ;

?>

cyrille.berliat[no spam]free.fr (17-Oct-2005 10:29)

Interfaces and Type Hinting can be used but not with Inherintance in the same time :

<?

class AbstractClass
{
    public function __ToString ( ) { return 'Here I\'m I'; }
}

class DescendantClass extends AbstractClass
{

}

interface MyI
{
    public function Hello ( AbstractClass $obj );
}

class MyClassOne implements MyI
{
    public function Hello ( AbstractClass $obj )
    {
        echo $obj;
    }
} // Will work as Interface Satisfied

class MyClassTwo implements MyI
{
    public function Hello ( DescendantClass $obj )
    {
        echo $obj;
    }
} // Will output a fatal error because Interfaces don't support Inherintance in TypeHinting

//Fatal error: Declaration of MyClassTwo::hello() must be compatible with that of MyI::hello()

?>

Something a little bit bad in PHP 5.0.4 :)

darealremco at msn dot com (02-Oct-2005 08:53)

To two notes below: There is one situation where classes and interfaces can be used interchangeably. In function definitions you can define parameter types to be classes or interfaces. If this was not so then there would not be much use for interfaces at all.

warhog at warhog dot net (11-Aug-2005 04:35)

on the post below:

An interface is in fact the same like an abstract class containing abstract methods, that's why interfaces share the same namespace as classes and why therefore "real" classes cannot have the same name as interfaces.

marcus at synchromedia dot co dot uk (28-Jul-2005 12:11)

Classes and interface names share a common name space, so you can't have a class and an interface with the same name, even though the two can never be used ambiguously (i.e. there are no circumstances in which a class and an interface can be used interchangeably). e.g. this will not work:

interface foo {
public function bling();
}

class foo implements foo {
public function bling() {
}
}

You will get a 'Cannot redeclare class' error, even though it's only been declared as a class once.

tobias_demuth at web dot de (04-May-2005 10:21)

The statement, that you have to implement _all_ methods of an interface has not to be taken that seriously, at least if you declare an abstract class and want to force the inheriting subclasses to implement the interface.
Just leave out all methods that should be implemented by the subclasses. But never write something like this:

<?php

interface Foo {

      function
bar();

}

abstract class
FooBar implements Foo {

       abstract function
bar(); // just for making clear, that this
                                 // method has to be implemented

}

?>

This will end up with the following error-message:

Fatal error: Can't inherit abstract function Foo::bar() (previously declared abstract in FooBar) in path/to/file on line anylinenumber

erik dot zoltan at msn dot com (25-Feb-2005 06:43)

When should you use interfaces?  What are they good for?
Here are two examples. 

1. Interfaces are an excellent way to implement reusability. 
You can create a general interface for a number of situations
(such as a save to/load from disk interface.)  You can then
implement the interface in a variety of different ways (e.g. for
formats such as tab delimited ASCII, XML and a database.) 
You can write code that asks the object to "save itself to
disk" without having to worry what that means for the object
in question.  One object might save itself to the database,
another to an XML and you can change this behavior over
time without having to rewrite the calling code. 

This allows you to write reusable calling code that can work
for any number of different objects -- you don't need to know
what kind of object it is, as long as it obeys the common
interface. 

2. Interfaces can also promote gradual evolution.  On a
recent project I had some very complicated work to do and I
didn't know how to implement it.  I could think of a "basic"
implementation but I knew I would have to change it later. 
So I created interfaces in each of these cases, and created
at least one "basic" implementation of the interface that
was "good enough for now" even though I knew it would have
to change later. 

When I came back to make the changes, I was able to create
some new implementations of these interfaces that added the
extra features I needed.  Some of my classes still used
the "basic" implementations, but others needed the
specialized ones.  I was able to add the new features to the
objects themselves without rewriting the calling code in most
cases.  It was easy to evolve my code in this way because
the changes were mostly isolated -- they didn't spread all
over the place like you might expect.

mat.wilmots (at) wanadoo (dot) fr (20-Jan-2005 02:22)

interfaces support multiple inheritance

<?php

interface SQL_Result extends SeekableIterator, Countable
{
   
// new stuff
}

abstract class
SQL_Result_Common
{
   
// just because that's what one would do in reality, generic implementation
}

class
SQL_Result_mysql extends SQL_Result_Common implements SQL_Result
{
  
// actual implementation
}

?>

This code raises a fatal error because SQL_Result_mysql doesn't implement the abstract methods of SeekableIterator (6) + Countable (1)

russ dot collier at gmail dot com (28-Nov-2004 06:24)

You can also specify class constants in interfaces as well (similar to specifying 'public static final' fields in Java interfaces):

<?php

interface FooBar
{

    const
SOME_CONSTANT = 'I am an interface constant';

    public function
doStuff();

}

?>

Then you can access the constant by referring to the interface name, or an implementing class, (again similar to Java) e.g.:

<?php

class Baz implements FooBar
{

   
//....

}

print
Baz::SOME_CONSTANT;
print
FooBar::SOME_CONSTANT;

?>

Both of the last print statements will output the same thing: the value of FooBar::SOME_CONSTANT