suche nach in der

Traits> <Klassenabstraktion
Last updated: Sat, 07 Jan 2012

view this page in

Interfaces

Interfaces erlauben die Erzeugung von Code, der spezifiziert, welche Methoden eine Klasse implementieren muss, ohne definieren zu müssen, wie diese Methoden behandelt werden.

Interfaces werden mit dem interface Schlüsselwort auf die selbe Weise wie eine Standardklasse definiert, ohne dass eine der Methoden ihren Inhalt definiert.

Alle in einem Interface deklarierten Methoden müssen public sein, dies liegt in der Natur eines Interfaces.

implements

Um ein Interface zu implementieren, wird der implements-Operator benutzt. Alle Methoden des Interfaces müssen innerhalb der Klasse implementiert werden; Unterlassung wird zu einem fatalen Fehler führen. Klassen dürfen, falls dies gewünscht wird, mehr als ein Interface implementieren, indem man die Interfaces voneinander mit einem Komma abtrennt.

Hinweis:

Eine Klasse kann nicht zwei Interfaces, die sich identische Funktionsnamen teilen, implementieren, da dies zu Doppeldeutigkeiten führen würde.

Hinweis:

Ein Interface kann ebenso wie eine Klasse mit Hilfe des Schlüsselwortes extends erweitert werden.

Konstanten

Ein Interface kann Konstanten definieren. Interface-Konstanten funktionieren genauso wie Klassenkonstanten. Eine Interfacekonstante kann von anderen Interfaces oder Klassen, die von diesem Interface erben, nicht verändert werden.

Beispiele

Beispiel #1 Interface-Beispiel

<?php
// Deklariere das Interface 'iTemplate'
interface iTemplate
{
    public function 
setVariable($name$var);
    public function 
getHtml($template);
}

// Implementiere das Interface
// Dies funktioniert
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;
    }
}

// Dies wird nicht funktionieren
// 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;
    }
}

?>

Beispiel #2 Interface-Vererbung

<?php
interface a

public function foo();


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

// Dies Funktioniert 
class implements b
{
  public function 
foo()
  {
  }

  public function 
baz(Baz $baz)
  {
  }
}

// Dies funktioniert nicht und führt zu einem fatalen Fehler
class implements b
{
  public function 
foo()
  {
  }

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

Beispiel #3 Interface-Mehrfachvererbung

<?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()
  {
  }
}
?>

Beispiel #4 Interfaces mit Konstanten

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

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

// Der folgende Abschnitt wird nicht funktionieren, da
// ein Überschreiben der Konstanten nicht gestattet ist.
// Dies ist das gleiche Konzept wie bei Klassenkonstanten.
class implements a
{
  const 
'Class constant';
}
?>

Siehe auch den instanceof-Operator.



add a note add a note User Contributed Notes
Interfaces
zedd at fadingtwilight dot net
05-Jul-2007 06: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 06: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).
prometheus at php-sparcle
12-Jun-2007 06:05
If I run the belowing code, I get an error message.

<?php

/**
 * Testing of method overrideing on interfaces
 */

interface IFoo
{
    public function
Foo();
}

interface
IBar extends IFoo
{
    public function
Foo($bar);
}

?>

The error message says: Fatal error: Can't inherit abstract function IFoo::Foo() (previously declared abstract in IBar) in D:\www\svn\virgilius\interface_or_test.php on line 12

So I don't understand that if method overriding works fine in class instances, but not in interfaces. BTW I think that is a typical situation when a standard method expanded by new parameters in the later interface instances.

I know, I can do a workaround with the func_get_* functions, but it's a big ugly hack I think. If I make a big class-hierarchie, I must make a lot of the above ugly think maybe, in a lot of methods, maybe.

So I prefer to droping all my interfaces and don't use ever again this stucture, because it's only make difficult to develop rather then it's make relieve and clean logically and overviewable.

Peace.
florian_mrt at hotmail dot com
08-Jun-2007 08:22
Classes can adopt interfaces, without the interface-specified functions, if they are inherited from parent classes.

<?php
interface object_interface
{
    public function
object_function();
}

abstract class
abstract_object
{
    public function
object_function()
    {
        print (
"This class is: abstract_object");
    }
}

class
child_object extends abstract_object implements object_interface
{
   
}

$OB = new child_object;
$OB->object_function();
?>
quickshiftin at gmail dot com
30-May-2007 06:16
to clarify (rather than just claim i think its a limitation) consider client code for
the abstract class FifthInterface.

Said client code must extend FifthInterface, thus using the only extension
available to that class.

really, i suppose it doesnt matter so much if we consider the client code could
just implement FirstInterface and SecondInterface itself.  Then, if there was a
FifthInterface

<?php
interface FifthInterface {
    public function
fifthInterface();
}
?>

the client class could just implement that as well.

hmmm....

I guess I just think interface inheritence affords cleaner designs.
Maikel
13-Jan-2007 12: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
}
?>
Maikel
12-Jan-2007 07:22
if you want to implement an interface and in addition you need to inherit, the correct order is:

<?php
class MyClassChildren extends MyClassParent implements MyInterface
{

}

?>
Dave
04-Jan-2007 07:15
vbolshov at rbc dot ru:

<?php

error_reporting
(E_ALL | E_STRICT);

interface
i {
       function
f($arg);
}
class
c implements i {
       function
f($arg, $arg2 = null)
       {
       }
}
?>

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

It wouldn't make sense to prevent this as you can *always* pass more arguments to a function than it requires, and the function can still use func_get_args() & co. to get them if it wants. e.g.

<?php
class c implements i {
       function
f($arg)
       {
             
$args2 = (func_num_args() >= 2 ? func_get_arg(2) : null);
       }
}
?>
Chris AT w3style DOT co.uk
07-Dec-2006 02: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 03: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 11: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.
albert at friendly dot net
19-Jul-2006 05:53
Maybe this is a bit like cyrille.berliat's problem plus a somewhat solution.

Let's say we want to create a queue class (or a stack, or a double
linked list, the usual... :-).
Wouldn't it be nice if we could define a generic interface or abstract (base) class that dictates the way specific queues have to look like ?
Without having to specify the type of data to be queued.
But we _do_ want to be strict about the type of data to be passed to a specific queue type.
In other words: a bit of generic programming.

Alas, it seems that Type Hinting and Interface/abstract don't get along :(
But there might be a more runtime-involved solution. See below.

So, this won't work:

------

abstract class Object {} // as PHP(5) doesn't have a super-Object-base-class

class Cdata extends Object { } // i.e. Cdata IS-A Object

interface Iqueue {
  public function enqueue(Object $data);
}

class Cmyqueue implements Iqueue {
 public function enqueue(Cdata $data) { }
}

$q = new Cmyqueue;
$data = new Cdata;
$q->enqueue($data);

------

Nor will this 'compile':

------

abstract class Object {}
class Cdata extends Object {}

abstract class Iqueue extends Object {
  abstract public function enqueue(Object $data);
}

class Cmyqueue extends Iqueue {
 public function enqueue(Cdata $data) { }
}

$q = new Cmyqueue;
$data = new Cdata;
$q->enqueue($data);

---------

This however is possible:

abstract class Object {}
class Cdata extends Object
{
 function __toString() { return('data'); }
}

abstract class Iqueue extends Object {
  abstract public function enqueue(Object $data);
}

class Cmyqueue extends Iqueue {
 public function enqueue(Object $data)
 { echo "enqueue '".$data->__toString()."'\n"; }
}

or:
interface Iqueue {
  public function enqueue(Object $data);
}
class Cmyqueue implements Iqueue {
 ....
}

We could do our special Cmyqueue specific pre-processing before enqueu()ing.
But the compiler won't warn us if we pass anything other than the
object we expect to be passed.
We'd have to do something runtime like this:

class Cmyqueue extends Iqueue {

 private function checkObjectType(Object &$obj)
 {
   if (get_class($obj) !== 'Cdata')
     throw new Exception("You can only pass CData's to Cmyqueue");
 }
 public function enqueue(Object $data)
 {
  $this->checkObjectType($data);
  echo "enqueue '".$data->__toString()."'\n";
 }

}

hope this clears up some...
Grigori Kochanov
17-Jul-2006 11:24
The engine does not recognise the class that implements an interface as declared in the code written before the class declaration is placed.
This means that you can't place the declaration of a classes that implements an interfaces in the code beneath the creation of an instance.

Tony2001 said this is an expected behaviour of Zend engine.

Back to PHP 3 ;-)

<?php
var_dump
(class_exists('validatorCheck'));
//you don't write $obj = new validatorCheck() here

class validatorCheck implements ArrayAccess {

function
offsetGet($key){}
function
offsetSet($key, $value) {}
function
offsetUnset($key) {}
function
offsetExists($offset) {}

//class end
}

var_dump(class_exists('validatorCheck'));
//an instance can be created only here
?>

Result:

bool(false)
bool(true)
spiritus.canis at gmail dot com
25-Oct-2005 07: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 11: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 :)
nuying117 at 163 dot com
13-Oct-2005 10:48
If a class implements two interfaces , but these two interfaces have a same method,for example
<?php
interface TestInterface1
{
    function
testMethod1();
    function
testMethod2();
}
interface
TestInterface2
{
    function
testMethod2();
    function
testMethod3();
    function
testMethod4();
}
class
ImplementClass implements TestInterface1,TestInterface2
{
    function
__construct()
    {
        echo
"I am constructor\r\n";
    }

    function
__destruct()
    {
        echo
"I am destructor\r\n";
    }

    function
testMethod1()
    {}
    function
testMethod2()
    {}
    function
testMethod3()
    {}
    function
testMethod4()
    {}
}
?>
It will cause  a fatal error!
darealremco at msn dot com
02-Oct-2005 09: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 05: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 01: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 11: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
Sebastian Mendel
11-Mar-2005 02:12
erik dot zoltan at msn dot com
25-Feb-2005 07: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 03: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)
m.kurzyna AT nius waw pl
24-Dec-2004 03:04
You can have a class implementing two or more interfaces, just seperate them with a coma:

<?php

interface i_one {
public
one();
}

interface
i_two {
public
two();
}

class
oneANDtwo implements i_one, i_two {
public
one() {}
public
two() {}
}

?>

Of course all implemented interfaces will be tested, so one needs to have one() and two() in their class to avoid errors.
russ dot collier at gmail dot com
28-Nov-2004 07: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

Traits> <Klassenabstraktion
Last updated: Sat, 07 Jan 2012