Ist es möglich, eine Schnittstelle mit privaten / geschützten Methoden zu haben?

76

Ist es in PHP 5 möglich, eine Schnittstelle mit privaten / geschützten Methoden zu haben?

Gerade habe ich:

interface iService
{
    private method1();
}

Das wirft einen Fehler:

Analysefehler: Syntaxfehler, unerwarteter T_STRING, Erwartung von T_VARIABLE

Ich möchte nur die Bestätigung haben, dass eine Schnittstelle nur öffentliche Methoden enthalten kann.

teepusink
quelle
2
Ich finde die Antwort enttäuschend. Ich möchte Schnittstellen, die auch geschützte / private Methoden unterstützen. Zum Beispiel habe ich eine Klasse, in der eine abstrakte öffentliche Methode auf einer geschützten Methode basiert, die von der Unterklasse implementiert wird. Ich möchte eine Schnittstelle verwenden, um Unterklassen zum Implementieren der geschützten Methoden zu benötigen, die für die abstrakten öffentlichen Methoden erforderlich sind.
Stoutie
4
Verwenden Sie zu diesem Zweck eine abstrakte Basisklasse. Sie können die beiden Ansätze kombinieren: öffentliche Methoden in der Schnittstelle, Implementierung dieser Methoden in einer abstrakten Basisklasse, die abstrakte geschützte Methoden definiert (und auf diesen basiert).
Stijn de Witt
2
Wenn Sie private oder geschützte Methoden deklarieren könnten, wäre dies private function method1 ();nicht der Fall private method1();.
tvanc

Antworten:

130

In der PHP-Handbuchseite zu Schnittstellen heißt es ausdrücklich:

Alle in einer Schnittstelle deklarierten Methoden müssen öffentlich sein. Dies ist die Natur einer Schnittstelle.

Ich denke, das erklärt den Fehler, den du bekommst ;-)

Pascal MARTIN
quelle
20

Schnittstellen werden verwendet, um öffentliche Methoden einer Klasse zu beschreiben, die diese Schnittstelle implementiert. Sie können niemals eine private Methode in einer Schnittstelle haben. Es wird davon ausgegangen, dass alle Methoden in einer Schnittstelle verwendet werden, und sie sollten nicht geändert werden.

Interfaces ist die PHP-Verbindung, dies ist jedoch Standard in der OO-Programmierung.

Ryanday
quelle
1
In anderen Sprachen wie Java können Sie Zugriffsmodifikatoren in Schnittstellen verwenden.
User123456
9

Im Allgemeinen kann eine Schnittstelle nur öffentliche Mitglieder haben, da die einzige Funktion einer Schnittstelle darin besteht, geerbt zu werden.

Aus dem PHPfreaks.com-Tutorial:

PHP5 verfügt über Schnittstellen. Nicht zu verwechseln mit Schnittstellen im allgemeineren Sinne. Mit dem Schlüsselwort interface wird eine Entität erstellt, mit der Klassen eine gemeinsame Schnittstelle erzwungen werden kann, ohne sie wie bei abstrakten Klassen erweitern zu müssen. Stattdessen wird eine Schnittstelle implementiert.

Schnittstellen unterscheiden sich von abstrakten Klassen. Zum einen sind sie eigentlich keine Klassen. Sie definieren keine Eigenschaften und sie definieren kein Verhalten. Die in einer Schnittstelle deklarierten Methoden müssen in Klassen deklariert werden, die sie implementieren.

Da eine Schnittstelle im allgemeineren Sinne eine Definition der Interaktion eines Objekts mit anderem Code ist, müssen alle Methoden als öffentlich deklariert werden (siehe Abschnitt zur Sichtbarkeit in diesem Kapitel). Bei Verwendung abstrakter Klassen kann eine abstrakte Methode jede Sichtbarkeit haben, aber die Implementierungen der erweiterten Klassen müssen dieselbe (oder schwächere) Sichtbarkeit verwenden. Durch das Implementieren einer Schnittstelle werden die Methoden der abstrakten Klasse als abstrakte Methoden hinzugefügt. Wenn sie nicht implementiert werden, führt dies zu einem Fehler wie dem folgenden:

Schwerwiegender Fehler: Klasse SomeConcreteClass enthält n abstrakte Methoden und muss daher als abstrakt deklariert werden oder die verbleibenden Methoden implementieren. Ja, abstrakte Klassen können Schnittstellen implementieren.

Webleeuw
quelle
4
Das ist schade. Weil ich eine öffentliche Methode, die von der Schnittstelle benötigt wird, in einer abstrakten Klasse implementieren lassen möchte, die auf einer geschützten Methode beruht, die auch von der Schnittstelle erzwungen wird. Auf diese Weise kann die abstrakte Klasse die öffentliche Schnittstelle bereitstellen, es liegt jedoch an den Unterklassen, die zugrunde liegende Logik zu implementieren. Sinn ergeben?
Stoutie
4
Scheint, als ob Sie möchten, dass die von der Unterklasse implementierte Methode abstrakt ist. Dann MUSS jede Unterklasse es implementieren. Aber es hat nichts mit der Schnittstelle zu tun.
Sven
6

Schnittstellen sind Typdeklarationen. Ein Typ besteht aus einer Reihe von Werten sowie einer Reihe von Operationen, die von außen ausgeführt werden können. Eine private Methode passt nicht in dieses Bild.

interface T {
  public /*int*/ function f(array $a);
}
interface U {
  public /*T*/ function g(T $t);
}

class C implements U {
    public function g(T $t) {
        ...
        $x = $t->f();
        ...
    }
}

Schnittstellen sind nützlich, weil sie die Schnittstellen von Objekten angeben. wie die Objekte mit ihrer Umgebung kommunizieren.

Nehmen wir jetzt an, wir T::fkönnten als privat deklariert werden. Wie wäre das für andere Objekte nützlich? es wäre nicht von außen aufrufbar, es wäre nicht Teil seiner Schnittstelle.

nur jemand
quelle
Einverstanden ... Aber es könnte geschützt werden, oder? Wie abstrakte Klassen erlauben ...
asdfasdfasdf
4

In vielen Fällen hilft eine Schnittstellendefinition anderen Modulen, das Verhalten und die API einer Klasse zu gewährleisten. In diesen Fällen können die anderen Module nicht auf private Methoden zugreifen oder diese verstehen. Deshalb können Sie niemals private Methoden auf eine Schnittstelle setzen.

Cristian Martinez
quelle
0

Big NO , jede Methode in der Schnittstelle hat niemals eine private oder geschützte Zugriffskennung.

** Alle in einer Schnittstelle deklarierten Methoden müssen öffentlich sein. Dies ist die Natur einer Schnittstelle.

Einige andere interessante Fakten zur Benutzeroberfläche

Schnittstellen können wie Klassen mit dem Operator "Erweitern" erweitert werden. Sie können nur andere Schnittstellen erweitern. (Quelle: https://www.php.net/manual/en/language.oop5.interfaces.php )

Beachten Sie, dass es möglich ist, einen Konstruktor in einer Schnittstelle zu deklarieren, was in einigen Kontexten nützlich sein kann, z. B. für die Verwendung durch Fabriken. Die Unterschrift sollte in der Kinderklasse gleich sein.

In Ihrem Fall besteht noch ein weiteres Problem darin, dass das Funktionsschlüsselwort in der Funktionsdeklaration fehlt. Es sollte sein

interface iService
{
    public function method1();
}
Amitesh Bharti
quelle
0

Wie bereits erwähnt, können Schnittstellen nur die öffentlich sichtbaren Methoden definieren. Ich wollte ein Beispiel zeigen, wie geschützte Methoden gehandhabt werden können. Um die Verwendung bestimmter geschützter Methoden zu erzwingen, kann eine abstrakte Klasse erstellt werden, die die Schnittstelle implementiert.

Dies ist insbesondere dann sinnvoll, wenn die abstrakte Klasse bereits einen Teil der Arbeitslast bewältigen kann, um die eigentliche Implementierung zu vereinfachen. Hier kümmert sich beispielsweise eine abstrakte Klasse um die Instanziierung des Ergebnisobjekts, das immer benötigt wird:

Zunächst die Schnittstelle.

interface iService
{
   /**
    * The method expects an instance of ServiceResult to be returned.
    * @return ServiceResult
    */
    public function doSomething();
}

Die abstrakte Klasse definiert dann die interne Methodenstruktur:

abstract class AbstractService implements iService
{
    public function doSomething()
    {
        // prepare the result instance, so extending classes
        // do not have to do it manually themselves.
        $result = new ServiceResult();

        $this->process($result);

        return $result;
    }

   /**
    * Force all classes that extend this to implement
    * this method.
    *
    * @param ServiceResult $result
    */
    abstract protected function process($result);
}

Die Klasse, die die eigentliche Implementierung ausführt, erbt die Schnittstelle automatisch von der abstact-Klasse und muss nur die geschützte Methode implementieren.

class ExampleService extends AbstractService
{
    protected function process($result)
    {
         $result->setSuccess('All done');
    }
}

Auf diese Weise erfüllt die Schnittstelle den öffentlichen Auftrag, und durch die AbstractServiceKlasse wird der interne Auftrag erfüllt. Die Anwendung muss nur die Verwendung der AbstractServiceKlasse erzwingen, wo dies zutreffend ist.

AeonOfTime
quelle