mirror of
https://github.com/php/doc-es.git
synced 2026-03-24 07:22:16 +01:00
848 lines
22 KiB
XML
848 lines
22 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<!-- EN-Revision: fc068b4857342eb409efeafe6723058f39ab1045 Maintainer: PhilDaiguille Status: ready -->
|
|
<!-- Reviewed: no Maintainer: Marqitos -->
|
|
<sect1 xml:id="language.oop5.basic" xmlns="http://docbook.org/ns/docbook">
|
|
<title>Sintaxis básica</title>
|
|
<sect2 xml:id="language.oop5.basic.class">
|
|
<title>class</title>
|
|
<para>
|
|
Una definición de clase básica comienza con la palabra clave
|
|
<literal>class</literal>, seguida del nombre de la clase.
|
|
Sigue un par de llaves que contienen la definición de las propiedades y los
|
|
métodos que pertenecen a la clase.
|
|
</para>
|
|
<para>
|
|
El nombre de la clase puede ser cualquiera siempre que no sea una
|
|
<link linkend="reserved">palabra reservada</link> en PHP.
|
|
A partir de PHP 8.4.0, el uso de un solo guion bajo <literal>_</literal> como nombre de clase es obsoleto.
|
|
Un nombre de clase válido comienza con una letra o un guion bajo,
|
|
seguido de cualquier número de letras, dígitos o guiones bajos.
|
|
En términos de expresión regular, esto se expresaría así:
|
|
<code>^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$</code>.
|
|
</para>
|
|
<para>
|
|
Una clase puede contener sus propias <link linkend="language.oop5.constants">constantes</link>,
|
|
<link linkend="language.oop5.properties">variables</link>
|
|
(llamadas "propiedades"), y funciones (llamadas "métodos").
|
|
</para>
|
|
<example>
|
|
<title>Definición típica de una clase</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class SimpleClass
|
|
{
|
|
// declaración de una propiedad
|
|
public $var = 'un valor por omisión';
|
|
|
|
// declaración de los métodos
|
|
public function displayVar() {
|
|
echo $this->var;
|
|
}
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
<para>
|
|
La pseudo-variable <varname>$this</varname> está disponible
|
|
cuando un método es llamado desde un contexto de objeto.
|
|
<varname>$this</varname> es el valor del objeto que llama.
|
|
</para>
|
|
<warning>
|
|
<para>
|
|
Llamar a un método no estático estáticamente lanza una
|
|
<classname>Error</classname>.
|
|
Antes de PHP 8.0.0, esto generaba una notificación de obsolescencia,
|
|
y <varname>$this</varname> no estaba definido.
|
|
</para>
|
|
<example xml:id="language.oop5.basic.class.this">
|
|
<title>Algunos ejemplos de la pseudo-variable <varname>$this</varname></title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class A
|
|
{
|
|
function foo()
|
|
{
|
|
if (isset($this)) {
|
|
echo '$this está definido (';
|
|
echo get_class($this);
|
|
echo ")\n";
|
|
} else {
|
|
echo "\$this no está definido.\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 está definido (A)
|
|
|
|
Deprecated: Non-static method A::foo() should not be called statically in %s on line 27
|
|
$this no está definido.
|
|
|
|
Deprecated: Non-static method A::foo() should not be called statically in %s on line 20
|
|
$this no está definido.
|
|
|
|
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 no está definido.
|
|
]]>
|
|
</screen>
|
|
&example.outputs.8;
|
|
<screen>
|
|
<![CDATA[
|
|
$this está definido (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>Clases de solo lectura (readonly)</title>
|
|
<para>
|
|
A partir de PHP 8.2.0, una clase puede ser marcada
|
|
con el modificador <modifier>readonly</modifier>.
|
|
Marcar una clase como <modifier>readonly</modifier> añadirá
|
|
el <link linkend="language.oop5.properties.readonly-properties">modificador <modifier>readonly</modifier></link>
|
|
a cada propiedad declarada, y evitará la creación
|
|
de <link linkend="language.oop5.properties.dynamic-properties">propiedades dinámicas</link>.
|
|
Además, no es posible añadir su soporte utilizando
|
|
el atributo <classname>AllowDynamicProperties</classname>.
|
|
Cualquier intento de hacerlo desencadenará un error de compilación.
|
|
</para>
|
|
<informalexample>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
#[\AllowDynamicProperties]
|
|
readonly class Foo {
|
|
}
|
|
|
|
// Fatal error: Cannot apply #[AllowDynamicProperties] to readonly class Foo
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
|
|
<para>
|
|
Como ni las propiedades no tipadas ni las propiedades estáticas
|
|
pueden ser marcadas con el modificador <literal>readonly</literal>,
|
|
las clases readonly no pueden declararlas:
|
|
</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>
|
|
Una clase <modifier>readonly</modifier> puede ser
|
|
<link linkend="language.oop5.basic.extends">extendida</link> si,
|
|
y solo si, la clase hija es también
|
|
una clase <modifier>readonly</modifier>.
|
|
</para>
|
|
</sect3>
|
|
|
|
</sect2>
|
|
|
|
<sect2 xml:id="language.oop5.basic.new">
|
|
<title>La palabra clave <literal>new</literal></title>
|
|
<para>
|
|
Para crear una instancia de una clase, la palabra clave <literal>new</literal> debe ser
|
|
utilizada. Un objeto será entonces sistemáticamente creado, a menos que tenga un
|
|
<link linkend="language.oop5.decon">constructor</link>
|
|
definido que lance una <link linkend="language.exceptions">excepción</link>
|
|
en caso de error. Las clases deben ser definidas antes de la instanciación (en
|
|
algunos casos, esto es imprescindible).
|
|
</para>
|
|
<para>
|
|
Si una variable <type>string</type> que contiene un nombre de clase es utilizada con
|
|
<literal>new</literal>, una nueva instancia de esa clase será creada.
|
|
Si la clase está en un espacio de nombres, su nombre completamente calificado debe ser utilizado.
|
|
</para>
|
|
|
|
<note>
|
|
<para>
|
|
Si no hay argumentos para pasar al constructor de la clase,
|
|
los paréntesis después del nombre de la clase pueden ser omitidos.
|
|
</para>
|
|
</note>
|
|
|
|
<example>
|
|
<title>Creación de una instancia</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
class SimpleClass {
|
|
}
|
|
|
|
$instance = new SimpleClass();
|
|
var_dump($instance);
|
|
|
|
// Esto también puede realizarse con una variable:
|
|
$className = 'SimpleClass';
|
|
$instance = new $className(); // new SimpleClass()
|
|
var_dump($instance);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
|
|
<para>
|
|
A partir de PHP 8.0.0, el uso de <literal>new</literal> con expresiones arbitrarias es soportado.
|
|
Esto permite instanciaciones más complejas si la expresión produce un
|
|
<type>string</type>. La expresión debe estar rodeada de paréntesis.
|
|
</para>
|
|
<example>
|
|
<title>Crear una instancia utilizando una expresión arbitraria</title>
|
|
<para>
|
|
En el ejemplo dado, se muestran varios ejemplos de expresiones
|
|
arbitrarias válidas que producen un nombre de clase.
|
|
Esto muestra una llamada de función, una concatenación de cadenas
|
|
y la constante <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>
|
|
En el contexto de la clase, es posible crear un nuevo objeto
|
|
con <literal>new self</literal> y <literal>new parent</literal>.
|
|
</para>
|
|
<para>
|
|
Al asignar una instancia ya creada de una clase a una variable,
|
|
la nueva variable accederá a la misma instancia que el objeto que fue asignado.
|
|
Este comportamiento es el mismo al pasar una instancia a una función.
|
|
Una copia de un objeto ya creado puede ser realizada por
|
|
<link linkend="language.oop5.cloning">clonación</link>.
|
|
</para>
|
|
<example>
|
|
<title>Asignación de un objeto</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class SimpleClass {
|
|
public string $var;
|
|
}
|
|
|
|
$instance = new SimpleClass();
|
|
|
|
$assigned = $instance;
|
|
$reference =& $instance;
|
|
|
|
$instance->var = '$assigned tendrá este valor';
|
|
|
|
$instance = null; // $instance y $reference se vuelven null
|
|
|
|
var_dump($instance);
|
|
var_dump($reference);
|
|
var_dump($assigned);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
NULL
|
|
NULL
|
|
object(SimpleClass)#1 (1) {
|
|
["var"]=>
|
|
string(30) "$assigned tendrá este valor"
|
|
}
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
<para>
|
|
Es posible crear una instancia de un objeto de varias maneras diferentes:
|
|
</para>
|
|
<example>
|
|
<title>Crear nuevos objetos</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
class Test
|
|
{
|
|
public static function getNew()
|
|
{
|
|
return new static();
|
|
}
|
|
}
|
|
|
|
class Child extends Test {}
|
|
|
|
$obj1 = new Test(); // Por el nombre de la clase
|
|
$obj2 = new $obj1; // A través de la variable que contiene un objeto
|
|
var_dump($obj1 !== $obj2);
|
|
|
|
$obj3 = Test::getNew(); // Por el método de clase
|
|
var_dump($obj3 instanceof Test);
|
|
|
|
$obj4 = Child::getNew(); // A través de un método de clase hija
|
|
var_dump($obj4 instanceof Child);
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
bool(true)
|
|
bool(true)
|
|
bool(true)
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
|
|
<para>
|
|
Es posible acceder a un miembro de un objeto recién
|
|
creado en una sola expresión:
|
|
</para>
|
|
<example>
|
|
<title>Acceder a un miembro de un objeto recién creado</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
echo (new DateTime())->format('Y'), PHP_EOL;
|
|
|
|
// los paréntesis alrededor son opcionales desde PHP 8.4.0
|
|
echo new DateTime()->format('Y'), PHP_EOL;
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs.similar;
|
|
<screen>
|
|
<![CDATA[
|
|
2025
|
|
2025
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
|
|
<note>
|
|
<simpara>
|
|
Anterior a PHP 7.1, los argumentos no son evaluados si no hay
|
|
función constructora definida.
|
|
</simpara>
|
|
</note>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="language.oop5.basic.properties-methods">
|
|
<title>Propiedades y métodos</title>
|
|
<para>
|
|
Las propiedades y métodos de clase viven en "espacios de nombres" separados,
|
|
por lo que es posible tener una propiedad y un método con el mismo nombre.
|
|
Hacer referencia tanto a una propiedad como a un método tienen la misma
|
|
notación, y el hecho de que una propiedad será accedida o que un método será llamado,
|
|
depende solo del contexto, es decir, si el uso es un acceso variable
|
|
o una llamada de función.
|
|
</para>
|
|
<example>
|
|
<title>Acceso a propiedad contra llamada de método</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class Foo
|
|
{
|
|
public $bar = 'propiedad';
|
|
|
|
public function bar() {
|
|
return 'método';
|
|
}
|
|
}
|
|
|
|
$obj = new Foo();
|
|
echo $obj->bar, PHP_EOL, $obj->bar(), PHP_EOL;
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
propiedad
|
|
método
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
<para>
|
|
Esto significa que llamar a una <link linkend="functions.anonymous">función
|
|
anónima</link> que ha sido asignada a una propiedad no es posible directamente.
|
|
En su lugar, la propiedad debe ser primero asignada a una variable.
|
|
Es posible llamar a este tipo de propiedad directamente
|
|
poniéndola entre paréntesis.
|
|
</para>
|
|
<example>
|
|
<title>Llamar a una función anónima almacenada en una propiedad</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">
|
|
<title>La palabra clave <literal>extends</literal></title>
|
|
<para>
|
|
Una clase puede heredar las constantes, métodos y propiedades de otra clase utilizando la palabra clave <literal>extends</literal> en la declaración.
|
|
No es posible extender múltiples clases: una clase puede
|
|
heredar solo de una clase base.
|
|
</para>
|
|
<para>
|
|
Las constantes, métodos y propiedades heredadas pueden ser redefinidas redeclarándolas con el
|
|
mismo nombre que en la clase padre. Sin embargo, si la clase padre ha definido
|
|
un método o constante como <link linkend="language.oop5.final">final</link>,
|
|
entonces estos no pueden ser redefinidos. Es posible acceder a los
|
|
métodos o propiedades estáticas redefinidas haciendo referencia a ellos con el operador
|
|
<link linkend="language.oop5.paamayim-nekudotayim">parent::</link>.
|
|
</para>
|
|
<note>
|
|
<simpara>
|
|
A partir de PHP 8.1.0, las constantes pueden ser declaradas como finales.
|
|
</simpara>
|
|
</note>
|
|
<example>
|
|
<title>Herencia simple de una clase</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class SimpleClass
|
|
{
|
|
function displayVar()
|
|
{
|
|
echo "Clase padre\n";
|
|
}
|
|
}
|
|
|
|
class ExtendClass extends SimpleClass
|
|
{
|
|
// Redefinición del método padre
|
|
function displayVar()
|
|
{
|
|
echo "Clase extendida\n";
|
|
parent::displayVar();
|
|
}
|
|
}
|
|
|
|
$extended = new ExtendClass();
|
|
$extended->displayVar();
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
Clase extendida
|
|
Clase padre
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
<sect3 xml:id="language.oop.lsp">
|
|
<title>Reglas de compatibilidad de firma</title>
|
|
<para>
|
|
Al sobrecargar un método, su firma debe ser compatible con
|
|
el método padre. De lo contrario, se emite un error fatal, o, anterior a
|
|
PHP 8.0.0, se genera un error de nivel <constant>E_WARNING</constant>.
|
|
Una firma es compatible si respeta las reglas de
|
|
<link linkend="language.oop5.variance">varianza</link>, hace un parámetro
|
|
obligatorio opcional, y solo si todos los nuevos parámetros son
|
|
opcionales y suavizan las reglas de visibilidad.
|
|
Esto es conocido como el Principio de Sustitución de Liskov
|
|
(Liskov Substitution Principle), o simplemente LSP.
|
|
El <link linkend="language.oop5.decon.constructor">constructor</link>,
|
|
y los métodos <literal>private</literal> están excluidos de estas reglas de
|
|
compatibilidad de firmas, y por lo tanto no emitirán un error fatal en caso de firma incompatible.
|
|
</para>
|
|
<example>
|
|
<title>Métodos hijos compatibles</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class Base
|
|
{
|
|
public function foo(int $a) {
|
|
echo "Válido\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[
|
|
Válido
|
|
Válido
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
|
|
<para>
|
|
Los siguientes ejemplos demuestran que un método hijo que elimina un parámetro,
|
|
o hace un parámetro opcional obligatorio, no es compatible con el método padre.
|
|
</para>
|
|
<example>
|
|
<title>Error fatal cuando un método hijo elimina un parámetro</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class Base
|
|
{
|
|
public function foo(int $a = 5) {
|
|
echo "Válido\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>Error fatal cuando un método hijo hace un parámetro opcional obligatorio</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class Base
|
|
{
|
|
public function foo(int $a = 5) {
|
|
echo "Válido\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>
|
|
Renombrar un parámetro de un método en una clase hija no es
|
|
una incompatibilidad de firma. Sin embargo, esto es desaconsejado ya que resultará en una <classname>Error</classname> en tiempo de ejecución si los
|
|
<link linkend="functions.named-arguments">argumentos nombrados</link>
|
|
son utilizados.
|
|
</para>
|
|
<example>
|
|
<title>Error al usar argumentos nombrados y cuando los parámetros han sido renombrados en una clase hija</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;
|
|
// Pasar parámetros según el contrato 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>
|
|
La palabra clave <literal>class</literal> también se utiliza
|
|
para la resolución de nombres de clases.
|
|
Es posible obtener el nombre completamente calificado de una clase
|
|
<literal>ClassName</literal> utilizando <literal>ClassName::class</literal>.
|
|
Esto es particularmente útil con las clases que utilizan
|
|
<link linkend="language.namespaces">espacios de nombres</link>.
|
|
</para>
|
|
<para>
|
|
<example xml:id="language.oop5.basic.class.class.name">
|
|
<title>Resolución de nombre de clase</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>
|
|
La resolución del nombre de clase utilizando <literal>::class</literal> es una
|
|
transformación durante la compilación. Es decir, en el instante en que se crea la cadena del
|
|
nombre de la clase, aún no se ha producido ninguna carga automática. Por lo tanto,
|
|
los nombres de clases se extienden incluso si la clase no existe. No se emite ningún error
|
|
en este caso.
|
|
</para>
|
|
<example xml:id="language.oop5.basic.class.class.fail">
|
|
<title>Resolución de nombre de clase faltante</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
print Does\Not\Exist::class;
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
Does\Not\Exist
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</note>
|
|
<para>
|
|
A partir de PHP 8.0.0, <literal>::class</literal> puede ser utilizado
|
|
en los objetos. Esta resolución ocurre durante la ejecución, y no durante la compilación. Sus efectos son los mismos que llamar
|
|
<function>get_class</function> en el objeto.
|
|
</para>
|
|
<example xml:id="language.oop5.basic.class.class.object">
|
|
<title>Resolución del nombre de un objeto</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>Métodos y propiedades nullsafe</title>
|
|
<para>
|
|
A partir de PHP 8.0.0, los métodos y propiedades también pueden ser accedidos
|
|
con el operador "nullsafe": <literal>?-></literal>. El operador nullsafe
|
|
funciona de manera idéntica al acceso de propiedades o métodos como si fuera arriba,
|
|
con la excepción de que si el objeto que se está desreferenciando es &null; entonces &null; será
|
|
devuelto en lugar de lanzar una excepción. Si la desreferencia se hace por una cadena, el resto de la cadena es ignorado.
|
|
</para>
|
|
<para>
|
|
El efecto es similar a rodear cada acceso con una verificación con
|
|
<function>is_null</function> primero, pero más compacto.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Operador nullsafe</title>
|
|
<programlisting role="php" annotations="non-interactive">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
// A partir de PHP 8.0.0, esta línea:
|
|
$result = $repository?->getUser(5)?->name;
|
|
|
|
// Es equivalente al siguiente bloque de código:
|
|
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>
|
|
El operador nullsafe es mejor utilizado cuando null es considerado un valor válido
|
|
y potencialmente esperado para una propiedad o valor de retorno de un método.
|
|
Para indicar un error, lanzar una excepción es preferible.
|
|
</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
|
|
-->
|