mirror of
https://github.com/php/doc-de.git
synced 2026-03-24 07:12:15 +01:00
879 lines
23 KiB
XML
879 lines
23 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<!-- EN-Revision: fc068b4857342eb409efeafe6723058f39ab1045 Maintainer: wiesemann Status: ready -->
|
|
<!-- Reviewed: yes -->
|
|
<!-- Rev-Revision: 5d1673b7a0e1a941111595d25cda663d8667a015 Reviewer: samesch -->
|
|
|
|
<sect1 xml:id="language.oop5.basic" xmlns="http://docbook.org/ns/docbook">
|
|
<title>Die Grundlagen</title>
|
|
|
|
<sect2 xml:id="language.oop5.basic.class">
|
|
<title>class</title>
|
|
<para>
|
|
Einfache Klassendefinitionen beginnen mit dem Schlüsselwort
|
|
<literal>class</literal>, gefolgt von einem Klassennamen, gefolgt von
|
|
einem Paar geschweifter Klammern, die die Definitionen der Eigenschaften
|
|
und Methoden der Klasse enthalten.
|
|
</para>
|
|
<para>
|
|
Der Klassenname kann ein beliebiger gültiger Bezeichner sein,
|
|
vorausgesetzt es ist kein von PHP
|
|
<link linkend="reserved">reserviertes Wort</link>.
|
|
Seit PHP 8.4.0 ist die Verwendung eines einzelnen Unterstrichs
|
|
<literal>_</literal> als Klassenname veraltet.
|
|
Ein gültiger Klassenname beginnt mit einem Buchstaben oder einem
|
|
Unterstrich, gefolgt von einer beliebigen Anzahl von Buchstaben, Ziffern
|
|
oder Unterstrichen; als regulärer Ausdruck formuliert:
|
|
<code>^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$</code>.
|
|
</para>
|
|
<para>
|
|
Eine Klasse darf aus ihren eigenen
|
|
<link linkend="language.oop5.constants">Konstanten</link>,
|
|
<link linkend="language.oop5.properties">Variablen</link>
|
|
("Eigenschaften" genannt) und Funktionen ("Methoden" genannt) bestehen.
|
|
</para>
|
|
<example>
|
|
<title>Definition einer einfachen Klasse</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class SimpleClass
|
|
{
|
|
// Deklaration einer Eigenschaft
|
|
public $var = 'ein Standardwert';
|
|
|
|
// Deklaration einer Methode
|
|
public function displayVar() {
|
|
echo $this->var;
|
|
}
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
<para>
|
|
Die Pseudovariable <varname>$this</varname> ist verfügbar, wenn eine
|
|
Methode aus einem Objektkontext heraus aufgerufen wird.
|
|
<varname>$this</varname> ist eine Referenz auf das aufgerufene Objekt.
|
|
</para>
|
|
<warning>
|
|
<para>
|
|
Wird eine nicht-statische Methode statisch aufgerufen, so wird ein
|
|
<classname>Error</classname> ausgelöst. Vor PHP 8.0.0 führte dies zu
|
|
einem Hinweis über das veraltete Verfahren und <varname>$this</varname>
|
|
war nicht definiert.
|
|
</para>
|
|
<example xml:id="language.oop5.basic.class.this">
|
|
<title>Einige Beispiele für die Pseudovariable <varname>$this</varname></title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class A
|
|
{
|
|
function foo()
|
|
{
|
|
if (isset($this)) {
|
|
echo '$this ist definiert (';
|
|
echo get_class($this);
|
|
echo ").\n";
|
|
} else {
|
|
echo "\$this ist nicht definiert.\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
class B
|
|
{
|
|
function bar()
|
|
{
|
|
A::foo();
|
|
}
|
|
}
|
|
|
|
$a = new A();
|
|
$a->foo();
|
|
|
|
A::foo();
|
|
|
|
$b = new B();
|
|
$b->bar();
|
|
|
|
B::bar();
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs.7;
|
|
<screen>
|
|
<![CDATA[
|
|
$this ist definiert (A).
|
|
|
|
Deprecated: Non-static method A::foo() should not be called statically in %s on line 27
|
|
$this ist nicht definiert.
|
|
|
|
Deprecated: Non-static method A::foo() should not be called statically in %s on line 20
|
|
$this ist nicht definiert.
|
|
|
|
Deprecated: Non-static method B::bar() should not be called statically in %s on line 32
|
|
|
|
Deprecated: Non-static method A::foo() should not be called statically in %s on line 20
|
|
$this ist nicht definiert.
|
|
]]>
|
|
</screen>
|
|
&example.outputs.8;
|
|
<screen>
|
|
<![CDATA[
|
|
$this ist definiert (A).
|
|
|
|
Fatal error: Uncaught Error: Non-static method A::foo() cannot be called statically in %s :27
|
|
Stack trace:
|
|
#0 {main}
|
|
thrown in %s on line 27
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</warning>
|
|
|
|
<sect3 xml:id="language.oop5.basic.class.readonly">
|
|
<title>Schreibgeschützte Klassen</title>
|
|
<para>
|
|
Seit PHP 8.2.0 kann eine Klasse mit dem Modifikator
|
|
<modifier>readonly</modifier> gekennzeichnet werden. Wenn eine Klasse als
|
|
<modifier>readonly</modifier> markiert wird, wird der
|
|
<link linkend="language.oop5.properties.readonly-properties">Modifikator <modifier>readonly</modifier></link>
|
|
zu jeder deklarierten Eigenschaft hinzugefügt und die Erstellung
|
|
<link linkend="language.oop5.properties.dynamic-properties">dynamischer Eigenschaften</link>
|
|
verhindert. Darüber hinaus ist es nicht möglich, die Unterstützung für
|
|
solche Eigenschaften mit Hilfe des Attributs
|
|
<classname>AllowDynamicProperties</classname> hinzuzufügen. Der Versuch,
|
|
dies zu tun, führt zu einem Fehler bei der Kompilierung.
|
|
</para>
|
|
<informalexample>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
#[\AllowDynamicProperties]
|
|
readonly class Foo {
|
|
}
|
|
|
|
// Fatal error: Cannot apply #[AllowDynamicProperties] to readonly class Foo
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
|
|
<para>
|
|
Da weder nicht typisierte noch statische Eigenschaften mit dem
|
|
<literal>readonly</literal>-Modifikator gekennzeichnet werden können,
|
|
können readonly-Klassen diese auch nicht deklarieren:
|
|
</para>
|
|
<informalexample>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
readonly class Foo
|
|
{
|
|
public $bar;
|
|
}
|
|
|
|
// Fatal error: Readonly property Foo::$bar must have type
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
readonly class Foo
|
|
{
|
|
public static int $bar;
|
|
}
|
|
|
|
// Fatal error: Readonly class Foo cannot declare static properties
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
<para>
|
|
Eine <modifier>readonly</modifier>-Klasse kann nur dann
|
|
<link linkend="language.oop5.basic.extends">erweitert</link> werden, wenn
|
|
die Kindklasse ebenfalls eine <modifier>readonly</modifier>-Klasse ist.
|
|
</para>
|
|
</sect3>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="language.oop5.basic.new">
|
|
<title>new</title>
|
|
<para>
|
|
Um eine Instanz einer Klasse zu erzeugen, muss das Schlüsselwort
|
|
<literal>new</literal> verwendet werden. Ein Objekt wird immer erzeugt,
|
|
außer das Objekt besitzt einen definierten
|
|
<link linkend="language.oop5.decon">Konstruktor</link>, der aufgrund eines
|
|
Fehlers eine <link linkend="language.exceptions">Exception</link> auslöst.
|
|
Klassen sollten vor ihrer Instantiierung definiert werden (in manchen
|
|
Fällen ist dies eine Notwendigkeit).
|
|
</para>
|
|
<para>
|
|
Wenn eine Variable, die einen <type>String</type> mit dem Namen einer
|
|
Klasse enthält, zusammen mit <literal>new</literal> verwendet wird, wird
|
|
eine neue Instanz dieser Klasse erzeugt. Falls sich die Klasse in einem
|
|
Namensraum befindet, muss der voll qualifizierte Name hierfür genutzt
|
|
werden.
|
|
</para>
|
|
|
|
<note>
|
|
<para>
|
|
Wenn dem Klassenkonstruktor keine Argumente übergeben werden müssen,
|
|
können die Klammern hinter dem Klassennamen weggelassen werden.
|
|
</para>
|
|
</note>
|
|
|
|
<example>
|
|
<title>Eine Instanz erzeugen</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class SimpleClass {
|
|
}
|
|
|
|
$instanz = new SimpleClass();
|
|
var_dump($instanz);
|
|
|
|
// dies ist auch mit einer Variablen möglich:
|
|
$klassenName = 'SimpleClass';
|
|
$instanz = new $klassenName(); // new SimpleClass()
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
<para>
|
|
Seit PHP 8.0.0 wird die Verwendung von <literal>new</literal> mit
|
|
beliebigen Ausdrücken unterstützt. Dies ermöglicht eine komplexere
|
|
Instanziierung, sofern der Ausdruck einen <type>&string;</type> erzeugt.
|
|
Die Ausdrücke müssen in Klammern eingeschlossen werden.
|
|
</para>
|
|
<example>
|
|
<title>Erzeugen einer Instanz mit einem beliebigen Ausdruck</title>
|
|
<para>
|
|
Hier werden mehrere Beispiele für gültige beliebige Ausdrücke gezeigt,
|
|
die einen Klassennamen erzeugen. Enthalten ist ein Funktionsaufruf, eine
|
|
String-Verkettung und die Konstante <constant>::class</constant>.
|
|
</para>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
class ClassA extends \stdClass {}
|
|
class ClassB extends \stdClass {}
|
|
class ClassC extends ClassB {}
|
|
class ClassD extends ClassA {}
|
|
|
|
function getSomeClass(): string
|
|
{
|
|
return 'ClassA';
|
|
}
|
|
|
|
var_dump(new (getSomeClass()));
|
|
var_dump(new ('Class' . 'B'));
|
|
var_dump(new ('Class' . 'C'));
|
|
var_dump(new (ClassD::class));
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs.8;
|
|
<screen>
|
|
<![CDATA[
|
|
object(ClassA)#1 (0) {
|
|
}
|
|
object(ClassB)#1 (0) {
|
|
}
|
|
object(ClassC)#1 (0) {
|
|
}
|
|
object(ClassD)#1 (0) {
|
|
}
|
|
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
<para>
|
|
Im Kontext einer Klasse ist es möglich, neue Objekte mit
|
|
<literal>new self</literal> und <literal>new parent</literal> anzulegen.
|
|
</para>
|
|
<para>
|
|
Wenn man eine bereits erzeugte Instanz einer Klasse einer neuen Variablen
|
|
zuweist, wird die neue Variable auf dieselbe Instanz zugreifen wie das
|
|
Objekt, das zugewiesen wurde. Dieses Verhalten ist dasselbe, wenn man
|
|
Instanzen an Funktionen übergibt. Eine Kopie eines bereits erzeugten
|
|
Objekts erhält man, indem man es
|
|
<link linkend="language.oop5.cloning">klont</link>.
|
|
</para>
|
|
<example>
|
|
<title>Objektzuweisung</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class SimpleClass {
|
|
public string $var;
|
|
}
|
|
|
|
$instanz = new SimpleClass();
|
|
|
|
$zugewiesen = $instanz;
|
|
$referenz =& $instanz;
|
|
|
|
$instanz->var = '$zugewiesen wird diesen Wert haben';
|
|
|
|
$instanz = null; // $instanz und $referenz werden null
|
|
|
|
var_dump($instanz);
|
|
var_dump($referenz);
|
|
var_dump($zugewiesen);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
NULL
|
|
NULL
|
|
object(SimpleClass)#1 (1) {
|
|
["var"]=>
|
|
string(34) "$zugewiesen wird diesen Wert haben"
|
|
}
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
<para>
|
|
Es gibt mehrere Möglichkeiten, Instanzen eines Objekts zu erzeugen:
|
|
</para>
|
|
<example>
|
|
<title>Erzeugen neuer Objekte</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
class Test
|
|
{
|
|
public static function getNew()
|
|
{
|
|
return new static();
|
|
}
|
|
}
|
|
|
|
class Child extends Test {}
|
|
|
|
$obj1 = new Test(); // Durch den Namen der Klasse
|
|
$obj2 = new $obj1(); // Durch die Variable, die ein Objekt enthält
|
|
var_dump($obj1 !== $obj2);
|
|
|
|
$obj3 = Test::getNew(); // Durch die Methode der Klasse
|
|
var_dump($obj3 instanceof Test);
|
|
|
|
$obj4 = Child::getNew(); // Durch eine Methode der Kindklasse
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
bool(true)
|
|
bool(true)
|
|
bool(true)
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
<para>
|
|
Es ist möglich, auf ein Mitglied eines neu erzeugten Objekts in einem
|
|
einzigen Ausdruck zuzugreifen:
|
|
</para>
|
|
<example>
|
|
<title>Zugriff auf ein Mitglied eines neu erzeugten Objekts</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
echo (new DateTime())->format('Y'), PHP_EOL;
|
|
// Seit PHP 8.4.0 sind umschließende Klammern optional
|
|
echo new DateTime()->format('Y'), PHP_EOL;
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs.similar;
|
|
<screen>
|
|
<![CDATA[
|
|
2025
|
|
2025
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
|
|
<note>
|
|
<simpara>
|
|
Vor PHP 7.1 werden die Argumente nicht ausgewertet, wenn keine
|
|
Konstruktor-Funktion definiert ist.
|
|
</simpara>
|
|
</note>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="language.oop5.basic.properties-methods">
|
|
<title>Eigenschaften und Methoden</title>
|
|
<para>
|
|
Klassen-Eigenschaften und -Methoden leben in separaten "Namensräumen", so
|
|
dass es eine Eigenschaft und eine Methode desselben Namens geben kann. Der
|
|
Zugriff auf eine Eigenschaft und eine Methode hat die gleiche Schreibweise
|
|
und ob auf eine Eigenschaft zugegriffen oder eine Methode aufgerufen wird,
|
|
hängt einzig und allein vom Kontext ab, &dh; ob die Verwendung ein
|
|
Variablenzugriff oder ein Funktionsaufruf ist.
|
|
</para>
|
|
<example>
|
|
<title>Variablenzugriff vs. Methodenaufruf</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class Foo
|
|
{
|
|
public $bar = 'Eigenschaft';
|
|
|
|
public function bar() {
|
|
return 'Methode';
|
|
}
|
|
}
|
|
|
|
$obj = new Foo();
|
|
echo $obj->bar, PHP_EOL, $obj->bar(), PHP_EOL;
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
Eigenschaft
|
|
Methode
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
<para>
|
|
Das bedeutet, dass der Aufruf einer
|
|
<link linkend="functions.anonymous">anonymen Funktion</link>, die einer
|
|
Eigenschaft zugewiesen wurde, nicht direkt möglich ist. Stattdessen muss
|
|
beispielsweise die Eigenschaft zunächst einer Variablen zugewiesen werden.
|
|
Es ist möglich, eine solche Eigenschaft direkt aufzurufen, indem man sie in
|
|
Klammern einschließt.
|
|
</para>
|
|
<example>
|
|
<title>Aufruf einer anonymen Funktion, die in einer Eigenschaft gespeichert ist</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class Foo
|
|
{
|
|
public $bar;
|
|
|
|
public function __construct() {
|
|
$this->bar = function() {
|
|
return 42;
|
|
};
|
|
}
|
|
}
|
|
|
|
$obj = new Foo();
|
|
|
|
echo ($obj->bar)(), PHP_EOL;
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
42
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="language.oop5.basic.extends">
|
|
<!-- TODO Example about class constant redefinition -->
|
|
<!-- TODO Split into it's own page? -->
|
|
<title>extends</title>
|
|
<para>
|
|
Eine Klasse kann die Konstanten, Methoden und Eigenschaften einer anderen
|
|
Klasse erben, indem man das Schlüsselwort <literal>extends</literal> in
|
|
der Deklaration benutzt. Es ist nicht möglich, mehrere Klassen zu
|
|
erweitern; eine Klasse kann nur eine einzige Basisklasse beerben.
|
|
</para>
|
|
<para>
|
|
Die geerbten Konstanten, Methoden und Eigenschaften können überschrieben
|
|
werden, indem sie mit demselben Namen neu deklariert werden, mit dem sie
|
|
in der Elternklasse definiert wurden. Falls die Elternklasse eine Methode
|
|
oder eine Konstante als <link linkend="language.oop5.final">final</link>
|
|
definiert hat, können diese nicht überschrieben werden. Es ist möglich,
|
|
auf die überschriebenen Methoden oder statischen Eigenschaften
|
|
zuzugreifen, wenn diese mittels
|
|
<link linkend="language.oop5.paamayim-nekudotayim">parent::</link>
|
|
referenziert werden.
|
|
</para>
|
|
<note>
|
|
<simpara>
|
|
Seit PHP 8.1.0 können Konstanten als final deklariert werden.
|
|
</simpara>
|
|
</note>
|
|
<example>
|
|
<title>Einfache Vererbung</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class SimpleClass
|
|
{
|
|
function displayVar()
|
|
{
|
|
echo "Elternklasse\n";
|
|
}
|
|
}
|
|
|
|
class ExtendClass extends SimpleClass
|
|
{
|
|
// Die Elternmethode überschreiben
|
|
function displayVar()
|
|
{
|
|
echo "Erweiternde Klasse\n";
|
|
parent::displayVar();
|
|
}
|
|
}
|
|
|
|
$extended = new ExtendClass();
|
|
$extended->displayVar();
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
Erweiternde Klasse
|
|
Elternklasse
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
|
|
<sect3 xml:id="language.oop.lsp">
|
|
<title>Regeln zur Signaturkompatibilität</title>
|
|
<para>
|
|
Wenn eine Methode überschrieben wird, so muss deren Signatur mit derjenigen
|
|
der Elternmethode kompatibel sein. Andernfalls wird ein fataler Fehler
|
|
hervorgerufen oder, vor PHP 8.0.0, eine Warnung der Stufe
|
|
<constant>E_WARNING</constant> ausgegeben. Eine Signatur ist kompatibel,
|
|
wenn sie die Regeln der <link linkend="language.oop5.variance">Varianz</link>
|
|
einhält, einen obligatorischen Parameter optional macht, nur neue optionale
|
|
Parameter hinzufügt und die Sichtbarkeit nicht einschränkt, sondern nur
|
|
lockert. Dies ist als das Liskovsche Substitutionsprinzip, kurz LSP,
|
|
bekannt. Der <link linkend="language.oop5.decon.constructor">Konstruktor</link>
|
|
sowie <literal>private</literal> Methoden sind von diesen Regeln zur
|
|
Signaturkompatibilität ausgenommen, weshalb im Fall einer Untimmigkeit in
|
|
der Signatur kein fataler Fehler hervorgerufen wird.
|
|
</para>
|
|
<example>
|
|
<title>Kompatible Kindmethoden</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
class Base
|
|
{
|
|
public function foo(int $a) {
|
|
echo "Gültig\n";
|
|
}
|
|
}
|
|
|
|
class Extend1 extends Base
|
|
{
|
|
function foo(int $a = 5)
|
|
{
|
|
parent::foo($a);
|
|
}
|
|
}
|
|
|
|
class Extend2 extends Base
|
|
{
|
|
function foo(int $a, $b = 5)
|
|
{
|
|
parent::foo($a);
|
|
}
|
|
}
|
|
|
|
$extended1 = new Extend1();
|
|
$extended1->foo();
|
|
$extended2 = new Extend2();
|
|
$extended2->foo(1);
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
Gültig
|
|
Gültig
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
|
|
<para>
|
|
Das folgende Beispiel demonstriert, dass eine Kindmethode nicht zur
|
|
Elternmethode kompatibel ist, wenn sie einen Parameter entfernt oder
|
|
einen optionalen Parameter notwendig macht.
|
|
</para>
|
|
<example>
|
|
<title>Fataler Fehler, wenn eine Kindmethode einen Parameter entfernt</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
class Base
|
|
{
|
|
public function foo(int $a = 5) {
|
|
echo "Gültig\n";
|
|
}
|
|
}
|
|
|
|
class Extend extends Base
|
|
{
|
|
function foo()
|
|
{
|
|
parent::foo(1);
|
|
}
|
|
}
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs.8.similar;
|
|
<screen>
|
|
<![CDATA[
|
|
Fatal error: Declaration of Extend::foo() must be compatible with Base::foo(int $a = 5) in /in/evtlq on line 13
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
<example>
|
|
<title>Fataler Fehler, wenn eine Kindmethode einen optionalen Parameter notwendig macht</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
class Base
|
|
{
|
|
public function foo(int $a = 5) {
|
|
echo "Gültig\n";
|
|
}
|
|
}
|
|
|
|
class Extend extends Base
|
|
{
|
|
function foo(int $a)
|
|
{
|
|
parent::foo($a);
|
|
}
|
|
}
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs.8.similar;
|
|
<screen>
|
|
<![CDATA[
|
|
Fatal error: Declaration of Extend::foo(int $a) must be compatible with Base::foo(int $a = 5) in /in/qJXVC on line 13
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
|
|
<warning>
|
|
<para>
|
|
Die Umbenennung eines Parameters einer Methode in einer Kindklasse führt
|
|
nicht zur Inkompatibilität. Es wird jedoch davon abgeraten, da es zu
|
|
Fehlern der Stufe <classname>Error</classname> führt, wenn
|
|
<link linkend="functions.named-arguments">benannte Parameter</link>
|
|
verwendet werden.
|
|
</para>
|
|
<example>
|
|
<title>Fehler, wenn benannte Parameter verwendet und diese in der Kindklasse umbenannt werden</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
class A {
|
|
public function test($foo, $bar) {}
|
|
}
|
|
|
|
class B extends A {
|
|
public function test($a, $b) {}
|
|
}
|
|
|
|
$obj = new B;
|
|
|
|
// Übergabe der Parameter gemäß den Konventionen von A::test()
|
|
$obj->test(foo: "foo", bar: "bar"); // ERROR!
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs.similar;
|
|
<screen>
|
|
<![CDATA[
|
|
Fatal error: Uncaught Error: Unknown named parameter $foo in /in/XaaeN:14
|
|
Stack trace:
|
|
#0 {main}
|
|
thrown in /in/XaaeN on line 14
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</warning>
|
|
</sect3>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="language.oop5.basic.class.class">
|
|
<title>::class</title>
|
|
|
|
<para>
|
|
Das Schlüsselwort <literal>class</literal> kann auch für die
|
|
Namensauflösung einer Klasse verwendet werden. Um den vollständig
|
|
qualifizierten Namen der Klasse <literal>ClassName</literal> zu erhalten,
|
|
kann <literal>ClassName::class</literal> verwendet werden. Dies ist vor
|
|
allem dann praktisch, wenn mit
|
|
<link linkend="language.namespaces">Namensräumen</link> gearbeitet wird.
|
|
</para>
|
|
<para>
|
|
<example xml:id="language.oop5.basic.class.class.name">
|
|
<title>Auflösung von Klassennamen</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
namespace NS {
|
|
class ClassName {
|
|
}
|
|
|
|
echo ClassName::class;
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
NS\ClassName
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</para>
|
|
<note>
|
|
<para>
|
|
Bei der Auflösung des Klassennamens unter Verwendung von
|
|
<literal>::class</literal> handelt es sich um eine Transformation zur
|
|
Übersetzungszeit. Das bedeutet, dass zu der Zeit, zu der die
|
|
Klassennamen-Zeichenkette erzeugt wird, noch kein Autoloading erfolgt ist.
|
|
Daraus folgt, dass Klassennamen erweitert werden, selbst wenn die Klasse
|
|
nicht existiert. In diesem Fall wird kein Fehler erzeugt.
|
|
</para>
|
|
<example xml:id="language.oop5.basic.class.class.fail">
|
|
<title>Fehlende Auflösung des Klassennamens</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
print Does\Not\Exist::class;
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
Does\Not\Exist
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</note>
|
|
<para>
|
|
Von PHP 8.0.0 an kann <literal>::class</literal> auch auf Objekte
|
|
angewendet werden. Diese Auflösung des Klassennamens erfolgt nicht zur
|
|
Übersetzungszeit, sondern zur Laufzeit. Sie hat die gleichen Auswirkungen
|
|
wie der Aufruf von <function>get_class</function> auf das Objekt.
|
|
</para>
|
|
<example xml:id="language.oop5.basic.class.class.object">
|
|
<title>Namensauflösung eines Objekts</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
namespace NS {
|
|
class ClassName {
|
|
}
|
|
|
|
$c = new ClassName();
|
|
print $c::class;
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
NS\ClassName
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</sect2>
|
|
<sect2 xml:id="language.oop5.basic.nullsafe">
|
|
<title>Nullsafe-Methoden und -Eigenschaften</title>
|
|
<para>
|
|
Von PHP 8.0.0 an kann auf Eigenschaften und Methoden stattdessen auch mit
|
|
dem "Nullsafe"-Operator zugegriffen werden: <literal>?-></literal>. Der
|
|
Nullsafe-Operator funktioniert genauso als Eigenschafts- oder
|
|
Methodenzugriff wie oben, mit dem Unterschied, dass &null; zurückgegeben
|
|
wird, statt dass eine Exception erzeugt wird, wenn das Objekt, das
|
|
dereferenziert wird, &null; ist. Wenn die Dereferenzierung Teil einer
|
|
Zeichenkette ist, wird der Rest der Zeichenkette übersprungen.
|
|
</para>
|
|
<para>
|
|
Der Effekt ist ähnlich, wie wenn man jeden Zugriff zuerst mit
|
|
<function>is_null</function> prüft, aber kompakter.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Nullsafe Operator</title>
|
|
<programlisting role="php" annotations="non-interactive">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
// Von PHP 8.0.0 an entspricht diese Zeile:
|
|
$result = $repository?->getUser(5)?->name;
|
|
|
|
// dem folgenden Codeblock:
|
|
if (is_null($repository)) {
|
|
$result = null;
|
|
} else {
|
|
$user = $repository->getUser(5);
|
|
if (is_null($user)) {
|
|
$result = null;
|
|
} else {
|
|
$result = $user->name;
|
|
}
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<note>
|
|
<para>
|
|
Der Nullsafe-Operator wird am besten verwendet, wenn Null ein gültiger
|
|
und potenziell erwarteter möglicher Rückgabewert für eine Eigenschaft
|
|
oder eine Methode ist. Um einen Fehler anzuzeigen, ist die Erzeugung
|
|
einer Exception vorzuziehen.
|
|
</para>
|
|
</note>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<!-- Keep this comment at the end of the file
|
|
Local variables:
|
|
mode: sgml
|
|
sgml-omittag:t
|
|
sgml-shorttag:t
|
|
sgml-minimize-attributes:nil
|
|
sgml-always-quote-attributes:t
|
|
sgml-indent-step:1
|
|
sgml-indent-data:t
|
|
indent-tabs-mode:nil
|
|
sgml-parent-document:nil
|
|
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
|
|
sgml-exposed-tags:nil
|
|
sgml-local-catalogs:nil
|
|
sgml-local-ecat-files:nil
|
|
End:
|
|
vim600: syn=xml fen fdm=syntax fdl=2 si
|
|
vim: et tw=78 syn=sgml
|
|
vi: ts=1 sw=1
|
|
-->
|