2010-12-07 6 views
8

Wenn ich eine Schnittstelle in PHP definiere, und eine Factory-Klasse, die eine Instanz dieser Schnittstelle erstellt, gibt es eine Möglichkeit, Client-Code zu zwingen, nur die Schnittstelle und nicht die zugrunde liegende konkrete Klasse zu verwenden? Aus meiner Sicht sind die Clients in der Lage, auch alle öffentlichen Funktionen/Felder in der zugrunde liegenden Klasse zu verwenden. HierWas ist der Zweck von Schnittstellen in PHP?

ein Beispiel:

<?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; 
} 
?> 

Antwort

6

Was Sie verlangen, ist nur mit einer statisch typisierten Sprache möglich, und da PHP dynamisch typisiert wird, ist die kurze Antwort, dass es nicht möglich ist.

Zum Beispiel könnte createMyInterface in Java IMyInterface zurückgeben, und die einzigen möglichen Operationen für dieses Objekt sind diejenigen, die in der Schnittstelle selbst definiert sind. Natürlich ist das Objekt wirklich vom Typ ConcreteImplOfMyInterface, so dass Sie es immer auf diesen Typ umwandeln können, um auf die anderen Felder/Methoden zuzugreifen.

PHP hat keine deklarierten Typen, also was Sie von einer Funktion zurückgeben, ist einfach eine "Variable" - sie hat keinen Typ. Und da es keine Typen gibt, sind alle Feld-/Methoden-Suchvorgänge dynamisch, so dass immer auf alles zugegriffen werden kann, was im Objekt "vorhanden" ist.

In gewisser Weise sind Schnittstellen in einer Sprache wie PHP etwas eingeschränkt - jede Klasse, die eine Schnittstelle implementiert, muss alle ihre Methoden implementieren, aber da gibt es keine Garantie, was eine Funktion in der erstens gibt es im Wesentlichen keine Garantie für irgendetwas. Am besten können Sie mit instanceof überprüfen, ob eine unbekannte Variable eine bestimmte Schnittstelle implementiert.

1

Machen Sie die Methoden privat.

return $myInterface.NotPartOfInterface; 

Funktioniert das? Ich denke nicht, dass es sollte. Ich denke du willst den :: Operator.

. wird nur zum Verketten von Strings verwendet.

9

Aus diesem Grund Schnittstellen in PHP gut sind:

interface Printable{ 
    public function display(); 
} 

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

Es erfordert, dass jede Variable in dieser Funktion eine Instanz von Druck sein würde. Sie zwingen also jeden, der Ihren Code verwendet, diese Schnittstelle zu implementieren, wenn Sie diese Funktion verwenden möchten.

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

Wenn Sie sicher, dass jemand anderes nicht in der Lage machen wollen, ist spezifische Methoden oder Variablen einer Klasse zu verwenden, müssen Sie diese Methoden und Variablen wie private definieren. Dadurch können sie nur von dieser bestimmten Klasse verwendet werden. (Nicht einmal Klassen, die Ihre Klasse erweitern, können sie verwenden)

+0

+1 für gute Sachen – alex

+0

Ich verstehe OOP Access Modifiers und ich weiß, dass PHP Typ Hinting hat. Die Tatsache, dass es keinen Typhinweis auf Funktionsrückgabetypen gibt, macht Interfaces für mich jedoch sinnlos. Was, wenn ich möchte, dass Klassen in derselben logischen Komponente öffentliche Methoden gegenseitig aufrufen können, aber ich wollte, dass diese Komponente als Ganzes öffentliche Schnittstellen verfügbar macht, die die einzige Möglichkeit darstellen, mit dieser Komponente zu kommunizieren? In PHP scheint das nicht möglich zu sein. – jameswelle

+0

Eine interessante Sache ist, dass Sie geschützte und sogar private Methoden/Variablen von Instanzen der aktuellen Klasse erreichen können. Wenn die Benutzerklasse beispielsweise die private Eigenschaft $ token hat, können Sie eine Methode innerhalb der Benutzerklasse haben: public function changeToken (Benutzer $ user) {$ user-> token = '1234'; } – Joe

2

Da PHP eine dynamische Sprache ist, bedeutet dies, dass alle Zugriffe auf Klassenmitglieder usw. zur Laufzeit aufgelöst werden. Das heißt, wenn ich einen Code habe, der $ foo-> bar() aufruft und ich ein Objekt in $ foo mit der Methode bar() erhalten habe, würde es aufgerufen werden, selbst wenn es nicht die Methodenleiste() wäre, die ich aufrufen wollte aber eine andere Methode auf einem anderen Objekt, das zufällig den gleichen Namen hat.

jedoch, dass gesagt wird, können Sie einen gewissen Schutz bieten durch typisierte Parameter angeben können nur bestimmte Objekte haben Funktion übernehmen:

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

Sie können jedoch nach wie vor nicht, dass jemand verbieten IMyInterface Implementierung und dann Funktionen schreiben, die akzeptiere IMyInterface, benutze es aber so, als wäre es Objekt einer höheren Klasse. Wie ich schon sagte, liegt das daran, dass PHP eine dynamische Sprache ist.