mirror of
https://github.com/php/doc-pt_br.git
synced 2026-03-23 22:52:12 +01:00
863 lines
22 KiB
XML
Executable File
863 lines
22 KiB
XML
Executable File
<?xml version="1.0" encoding="utf-8"?>
|
|
<!-- EN-Revision: c1f37a6c270aadbbb3da56a3973ffd62197adf2b Maintainer: leonardolara Status: ready --><!-- CREDITS: ae,amandavale,narigone,fabioluciano,lhsazevedo,leonardolara -->
|
|
|
|
<sect1 xml:id="language.oop5.basic" xmlns="http://docbook.org/ns/docbook">
|
|
<title>O básico</title>
|
|
|
|
<sect2 xml:id="language.oop5.basic.class">
|
|
<title>class</title>
|
|
<para>
|
|
A definição de uma classe começa com a
|
|
palavra chave <literal>class</literal>, seguida do nome da classe,
|
|
seguido de um par de chaves que englobam as definições
|
|
de propriedades e métodos pertencentes à classe.
|
|
</para>
|
|
<para>
|
|
O nome de uma classe pode ser qualquer identificador válido, que não seja
|
|
uma <link linkend="reserved">palavra reservada</link> do PHP.
|
|
A partir do PHP 8.4.0, usar um único sublinhado <literal>_</literal> como
|
|
nome de classe foi descontinuado.
|
|
Um nome de classe válido começa com uma letra ou sublinhado,
|
|
seguido de qualquer sequência de letras, números e sublinhados.
|
|
Como uma expressão regular, pode ser expressada assim:
|
|
<code>^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$</code>.
|
|
</para>
|
|
<para>
|
|
Uma classe pode conter suas
|
|
próprias <link linkend="language.oop5.constants">constantes</link>, <link linkend="language.oop5.properties">variáveis</link>
|
|
(chamadas de "propriedades") e funções (chamadas de "métodos").
|
|
</para>
|
|
<example>
|
|
<title>Definição Simples de uma Classe</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class SimpleClass
|
|
{
|
|
// declaração de propriedade
|
|
public $var = 'um valor padrão';
|
|
|
|
// declaração de método
|
|
public function displayVar() {
|
|
echo $this->var;
|
|
}
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
<para>
|
|
A pseudo-variável <varname>$this</varname> está disponível quando um
|
|
método é chamado a partir de um contexto de um objeto.
|
|
<varname>$this</varname> é o valor do objeto chamado.
|
|
</para>
|
|
<warning>
|
|
<para>
|
|
Chamar um método não estático de maneira estática lança um
|
|
<classname>Error</classname>.
|
|
Anteriormente ao PHP 8.0.0, isto iria gerar um aviso de descontinuação,
|
|
e <varname>$this</varname> estaria indefinido.
|
|
</para>
|
|
<example xml:id="language.oop5.basic.class.this">
|
|
<title>Alguns exemplos da pseudo variável <varname>$this</varname></title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class A
|
|
{
|
|
function foo()
|
|
{
|
|
if (isset($this)) {
|
|
echo '$this está definida (';
|
|
echo get_class($this);
|
|
echo ")\n";
|
|
} else {
|
|
echo "\$this não está definida.\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á definida (A)
|
|
|
|
Deprecated: Non-static method A::foo() should not be called statically in %s on line 27
|
|
$this não está definida.
|
|
|
|
Deprecated: Non-static method A::foo() should not be called statically in %s on line 20
|
|
$this não está definida.
|
|
|
|
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 não está definida.
|
|
]]>
|
|
</screen>
|
|
&example.outputs.8;
|
|
<screen>
|
|
<![CDATA[
|
|
$this está definida (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>Classes somente leitura</title>
|
|
<para>
|
|
A partir do PHP 8.2.0, uma classe pode ser marcada com o modificador
|
|
<modifier>readonly</modifier>.
|
|
Marcar uma classe como <modifier>readonly</modifier> irá acrescentar o modificador
|
|
<link linkend="language.oop5.properties.readonly-properties"><modifier>readonly</modifier></link>
|
|
em cada propriedade declarada, e prevenir a criação de
|
|
<link linkend="language.oop5.properties.dynamic-properties">propriedades dinâmicas</link>.
|
|
Além disso será impossível de acrescentar suportes a propriedades dinâmicas utilizando o atributo
|
|
<classname>AllowDynamicProperties</classname>. Acrescentar o atributo em classes somente leitura
|
|
irá disparar um erro de compilação.
|
|
</para>
|
|
<informalexample>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
#[\AllowDynamicProperties]
|
|
readonly class Foo {
|
|
}
|
|
|
|
// Fatal error: Cannot apply #[AllowDynamicProperties] to readonly class Foo
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
|
|
<para>
|
|
Como as propriedades estáticas ou sem tipo não podem ser marcadas com o
|
|
modificador <literal>readonly</literal>, as classes somente leitura também não podem
|
|
declará-las:
|
|
</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>
|
|
Uma classe <modifier>readonly</modifier> pode ser
|
|
<link linkend="language.oop5.basic.extends">estendida</link>
|
|
se, e somente se, a classe filha também ser uma classe
|
|
<modifier>readonly</modifier>.
|
|
</para>
|
|
</sect3>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="language.oop5.basic.new">
|
|
<title>new</title>
|
|
<para>
|
|
Para criar uma instância de uma classe, a instrução <literal>new</literal> deve
|
|
ser utilizada. Um objeto sempre será criado a não ser que a classe tenha um
|
|
<link linkend="language.oop5.decon">construtor</link> definido que dispare uma
|
|
<link linkend="language.exceptions">exceção</link> em caso de erro. Classes
|
|
devem ser definidas antes de instanciadas (e em alguns casos isso é
|
|
obrigatório).
|
|
</para>
|
|
<para>
|
|
Se uma variável contendo uma <type>string</type> com o nome da classe for utilizado com
|
|
<literal>new</literal>, uma nova instância da classe será criada. Se
|
|
a classe estiver dentro de um namespace, seu nome qualificado completo deve ser utilizado
|
|
ao fazer isto.
|
|
</para>
|
|
|
|
<note>
|
|
<para>
|
|
Se não há argumentos a serem passados para o construtor da classe,
|
|
os parênteses após o nome da classe podem ser omitidos.
|
|
</para>
|
|
</note>
|
|
|
|
<example>
|
|
<title>Criando uma instância</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class SimpleClass {
|
|
}
|
|
|
|
$instance = new SimpleClass();
|
|
var_dump($instance);
|
|
|
|
// Também pode ser feito com uma variável:
|
|
$className = 'SimpleClass';
|
|
$instance = new $className(); // new SimpleClass()
|
|
var_dump($instance);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
<para>
|
|
A partir do PHP 8.0.0, usar <literal>new</literal> com expressões arbitrárias
|
|
é suportado. Isso permite instanciação mais complexa se a expressão
|
|
produzir uma <type>string</type>. As expressões devem ser envolvidas em parênteses.
|
|
</para>
|
|
<example>
|
|
<title>Criando uma instância usando uma expressão arbitrária</title>
|
|
<para>
|
|
No exemplo fornecido mostramos múltiplos exemplos de expressões arbitrárias válidas que produzem um nome de classe.
|
|
Isto mostra uma chamada para uma função, concatenação de string, e a constante <constant>::class</constant>.
|
|
</para>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
class ClasseA extends \stdClass {}
|
|
class ClasseB extends \stdClass {}
|
|
class ClasseC extends ClasseB {}
|
|
class ClasseD extends ClasseA {}
|
|
|
|
function obterAlgumaClasse(): string
|
|
{
|
|
return 'ClasseA';
|
|
}
|
|
|
|
var_dump(new (obterAlgumaClasse()));
|
|
var_dump(new ('Classe' . 'B'));
|
|
var_dump(new ('Classe' . 'C'));
|
|
var_dump(new (ClasseD::class));
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs.8;
|
|
<screen>
|
|
<![CDATA[
|
|
object(ClasseA)#1 (0) {
|
|
}
|
|
object(ClasseB)#1 (0) {
|
|
}
|
|
object(ClasseC)#1 (0) {
|
|
}
|
|
object(ClasseD)#1 (0) {
|
|
}
|
|
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
<para>
|
|
No contexto da classe, é possível criar um novo objeto com
|
|
<literal>new self</literal> e <literal>new parent</literal>.
|
|
</para>
|
|
<para>
|
|
Ao atribuir uma instância de uma classe já criada, a uma variável nova,
|
|
a variável nova irá acessar a mesma instância do objeto que foi atribuído. Este
|
|
comportamento se mantém ao se passar instâncias a uma função. Uma cópia
|
|
de um objeto criado pode ser feita
|
|
<link linkend="language.oop5.cloning">clonando</link> o mesmo.
|
|
</para>
|
|
<example>
|
|
<title>Atribuição de Objetos</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class SimpleClass {
|
|
public string $var;
|
|
}
|
|
|
|
$instance = new SimpleClass();
|
|
|
|
$assigned = $instance;
|
|
$reference =& $instance;
|
|
|
|
$instance->var = '$assigned terá esse valor';
|
|
|
|
$instance = null; // $instance e $reference tornam-se nulos
|
|
|
|
var_dump($instance);
|
|
var_dump($reference);
|
|
var_dump($assigned);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
NULL
|
|
NULL
|
|
object(SimpleClass)#1 (1) {
|
|
["var"]=>
|
|
string(30) "$assigned terá esse valor"
|
|
}
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
<para>
|
|
É possível usar algumas formas de criar instâncias de um objeto:
|
|
</para>
|
|
<example>
|
|
<title>Criando novos objetos</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
class Test
|
|
{
|
|
public static function getNew()
|
|
{
|
|
return new static();
|
|
}
|
|
}
|
|
|
|
class Child extends Test {}
|
|
|
|
$obj1 = new Test(); // Usando o nome da classe
|
|
$obj2 = new $obj1(); // Usando a variável que contém o objeto
|
|
var_dump($obj1 !== $obj2);
|
|
|
|
$obj3 = Test::getNew(); // Usando o método da classe
|
|
var_dump($obj3 instanceof Test);
|
|
|
|
$obj4 = Child::getNew(); // Usando o método através da classe filha
|
|
var_dump($obj4 instanceof Child);
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
bool(true)
|
|
bool(true)
|
|
bool(true)
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
|
|
<para>
|
|
É possível acessar um membro do objeto recém criado
|
|
em uma expressão simples:
|
|
</para>
|
|
<example>
|
|
<title>Acessando um membro de um novo objeto criado</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
echo (new DateTime())->format('Y'), PHP_EOL;
|
|
|
|
// parênteses envolvendo o objeto são opcionais a partir do PHP 8.4.0
|
|
echo new DateTime()->format('Y'), PHP_EOL;
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs.similar;
|
|
<screen>
|
|
<![CDATA[
|
|
2025
|
|
2025
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
|
|
<note>
|
|
<simpara>
|
|
Anteriormente ao PHP 7.1, os argumentos não são avaliados se não houver
|
|
um construtor definido.
|
|
</simpara>
|
|
</note>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="language.oop5.basic.properties-methods">
|
|
<title>Propriedades e métodos</title>
|
|
<para>
|
|
Propriedades e métodos de classe vivem em "namespaces" separados, de forma que é
|
|
possível ter uma propriedade e método com mesmos nomes. A referência a
|
|
propriedades e métodos tem a mesma notação, e a decisão de se uma propriedade será acessada
|
|
ou uma chamada a um método feita, depende somente do contexto,
|
|
ou seja, se está tentando acessar uma variável ou chamar um método.
|
|
</para>
|
|
<example>
|
|
<title>Acesso a propriedade vs. chamar um método</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class Foo
|
|
{
|
|
public $bar = 'propriedade';
|
|
|
|
public function bar() {
|
|
return 'métod';
|
|
}
|
|
}
|
|
|
|
$obj = new Foo();
|
|
echo $obj->bar, PHP_EOL, $obj->bar(), PHP_EOL;
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
propriedade
|
|
método
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
<para>
|
|
Isto significa que chamar diretamente uma <link linkend="functions.anonymous">função
|
|
anônima</link> atribuída a uma propriedade não é possível.
|
|
Em vez disso, por exemplo, a propriedade deve primeiro ser atribuída a uma
|
|
variável. É possível chamar uma propriedade diretamente
|
|
colocando-a entre parênteses.
|
|
</para>
|
|
<example>
|
|
<title>Chamando uma função anônima armazenada em uma propriedade</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>
|
|
Uma classe pode herdar constantes, métodos e propriedades de outra classe usando a
|
|
palavra-chave <literal>extends</literal> na declaração
|
|
da classe. Não é possível herdar múltiplas classes; uma
|
|
classe só pode herdar uma classe base.
|
|
</para>
|
|
<para>
|
|
Os métodos e propriedades herdados podem ser sobrescritos
|
|
declarando-os com o mesmo nome definido na classe
|
|
base. Entretanto, se a classe mãe definiu um método ou constante
|
|
como <link linkend="language.oop5.final">final</link>,
|
|
eles não poderão ser sobrescritos. É possível acessar os métodos sobrescritos
|
|
ou propriedades estáticas referenciado-os
|
|
com <link linkend="language.oop5.paamayim-nekudotayim">parent::</link>.
|
|
</para>
|
|
<note>
|
|
<simpara>
|
|
A partir do PHP 8.1.0, constantes podem ser declaradas como finais.
|
|
</simpara>
|
|
</note>
|
|
<example>
|
|
<title>Herança simples de classe</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class SimpleClass
|
|
{
|
|
function displayVar()
|
|
{
|
|
echo "Parent class\n";
|
|
}
|
|
}
|
|
|
|
class ExtendClass extends SimpleClass
|
|
{
|
|
// Redefine o método pai
|
|
function displayVar()
|
|
{
|
|
echo "Classe Herdeira\n";
|
|
parent::displayVar();
|
|
}
|
|
}
|
|
|
|
$extended = new ExtendClass();
|
|
$extended->displayVar();
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
Classe Herdeira
|
|
um valor padrão
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
|
|
<sect3 xml:id="language.oop.lsp">
|
|
<title>Regras de compatibilidade de assinaturas</title>
|
|
<para>
|
|
Ao sobrescrever um método, sua assinatura precisa ser compatível com
|
|
a do método original. Caso contrário um erro fatal é emitido, ou, antes do PHP 8.0.0, um alerta
|
|
<constant>E_WARNING</constant> seria gerado.
|
|
Uma assinatura é compatível se ela respeita as regras de
|
|
<link linkend="language.oop5.variance">variância</link>, se ela transforma um
|
|
parâmetro obrigatório em opcional, se ela adiciona novos parâmetros opcionais,
|
|
e se ela não restringe ou apenas aumenta a visibilidade.
|
|
Isso é conhecido como Princípio de Substituição de Liskov, ou LSP.
|
|
O <link linkend="language.oop5.decon.constructor">construtor</link>,
|
|
e membros <literal>private</literal> não precisam seguir essas regras de
|
|
compatibilidade, e portanto não há emissão de erros fatais no caso
|
|
de assinaturas incompatíveis.
|
|
</para>
|
|
<example>
|
|
<title>Métodos compatíveis</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
class Base
|
|
{
|
|
public function foo(int $a) {
|
|
echo "Valid\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[
|
|
Valid
|
|
Valid
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
|
|
<para>
|
|
Os exemplos a seguir demonstram que um método derivado, que remove um parâmetro ou transforma um parâmetro opcional
|
|
em mandatório, não é compatível com o método original.
|
|
</para>
|
|
<example>
|
|
<title>Erro fatal quando um método derivado remove um 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>Erro fatal quando um método derivado transforma um parâmetro opcional em mandatório</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>
|
|
Renomear um parâmetro em uma classe derivada não é uma quebra
|
|
de assinatura. Entretanto isso é desencorajado porque ocasionará um
|
|
<classname>Error</classname> se
|
|
<link linkend="functions.named-arguments">argumentos nomeados</link>
|
|
forem utilizados na chamada.
|
|
</para>
|
|
<example>
|
|
<title>Erro ao utilizar argumentos renomeados em uma classe derivada</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;
|
|
|
|
// Passando parâmetros de acordo com o contrato de 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>
|
|
A palavra-chave <literal>class</literal> também pode ser utilizada para resolução
|
|
de nome de classes.
|
|
Pode-se obter o nome completo e qualificado da classe <literal>ClassName</literal>
|
|
utilizando <literal>ClassName::class</literal>. Isso é particularmente útil em classes com
|
|
<link linkend="language.namespaces">namespaces</link>.
|
|
</para>
|
|
<para>
|
|
<example xml:id="language.oop5.basic.class.class.name">
|
|
<title>Resolução de nome da classe</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>A resolução do nome de classe através de <literal>::class</literal> é
|
|
uma transformação em tempo de compilação. Isso significa que no momento em que o texto do nome
|
|
da classe é criado, o auto carregamento ainda não ocorreu. Como consequência, nomes de classe
|
|
são expandidos mesmo se a classe não existir. Não é emitido erro nestes
|
|
casos.
|
|
</para>
|
|
<example xml:id="language.oop5.basic.class.class.fail">
|
|
<title>Resolução de um nome de classe ausente</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 do PHP 8.0.0, a constante <literal>::class</literal> também pode ser utilizada em
|
|
objetos. Essa resolução acontece em tempo de execução, e não em tempo de compilação. O efeito é
|
|
o mesmo de chamar <function>get_class</function> em um objeto.
|
|
</para>
|
|
<example xml:id="language.oop5.basic.class.class.object">
|
|
<title>Resolução de nome de 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 e propriedades nullsafe</title>
|
|
<para>
|
|
A partir do PHP 8.0.0, propriedades e métodos também podem ser acessados com o operador
|
|
"nullsafe": <literal>?-></literal>. O operador nullsafe
|
|
funciona da mesma forma que os acessos de métodos e variáveis, exceto que se
|
|
o objeto referenciado é &null;, então &null;
|
|
será retornado ao invés de uma exceção ser lançada. Se uma desreferência for parte de uma
|
|
cadeia de chamadas, o resto da cadeia é ignorado.
|
|
</para>
|
|
<para>
|
|
O resultado é similar a encapsular cada acesso dentro de um teste <function>is_null</function>,
|
|
mas mais compacto.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Operador nullsafe</title>
|
|
<programlisting role="php" annotations="non-interactive">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
// A partir do PHP 8.0.0, esta linha:
|
|
$result = $repository?->getUser(5)?->name;
|
|
|
|
// É o equivalente ao seguinte 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>
|
|
O operador nullsafe é melhor utilizado quando null é considerado um valor válido
|
|
e esperado de uma propriedade ou retorno de método. Para indicar um erro,
|
|
uma exceção lançada é preferível.
|
|
</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
|
|
-->
|