Files
archived-doc-pt-br/language/oop5/overloading.xml
Leonardo Lara Rodrigues 9828cfe6ff sync with en rev
2025-03-06 15:24:15 -03:00

333 lines
11 KiB
XML
Executable File

<?xml version="1.0" encoding="utf-8"?>
<!-- EN-Revision: d6f54016d62904cfd8200604aadd5e3f0d9bad97 Maintainer: leonardolara Status: ready --><!-- CREDITS: ae,narigone,amandavale,fabioluciano,leonardolara -->
<sect1 xml:id="language.oop5.overloading" xmlns="http://docbook.org/ns/docbook">
<title>Sobrecarga</title>
<para>
Sobrecarga em PHP provê recursos para <quote>criar</quote>
dinamicamente propriedades e métodos.
Estas entidades dinâmicas são processadas por métodos mágicos fornecendo
a uma classe vários tipos de ações.
</para>
<para>
Os métodos de sobrecarga são invocados ao interagir com propriedades ou
métodos que não foram declarados ou não são
<link linkend="language.oop5.visibility">visíveis</link> no
escopo corrente. O resto desta seção usará os termos
<quote>propriedades inacessíveis</quote> e <quote>métodos inacessíveis</quote>
para referir-se a esta combinação de declaração
e visibilidade.
</para>
<para>
Todos os métodos de sobrecarga devem ser definidos como <literal>public</literal>.
</para>
<note>
<para>
Nenhum dos argumentos dos métodos mágicos podem ser
<link linkend="functions.arguments.by-reference">passados por
referência</link>.
</para>
</note>
<note>
<para>
A interpretação do PHP de <quote>sobrecarga</quote> é diferente da
maioria das linguagens orientadas a objeto. Sobrecarga, tradicionalmente,
provê a habilidade de ter múltiplos métodos com o mesmo nome, mas
com quantidades e tipos de argumentos
diferentes.
</para>
</note>
<sect2 xml:id="language.oop5.overloading.members">
<title>Sobrecarga de propriedades</title>
<methodsynopsis xml:id="object.set">
<modifier>public</modifier> <type>void</type><methodname>__set</methodname>
<methodparam><type>string</type><parameter>name</parameter></methodparam>
<methodparam><type>mixed</type><parameter>value</parameter></methodparam>
</methodsynopsis>
<methodsynopsis xml:id="object.get">
<modifier>public</modifier> <type>mixed</type><methodname>__get</methodname>
<methodparam><type>string</type><parameter>name</parameter></methodparam>
</methodsynopsis>
<methodsynopsis xml:id="object.isset">
<modifier>public</modifier> <type>bool</type><methodname>__isset</methodname>
<methodparam><type>string</type><parameter>name</parameter></methodparam>
</methodsynopsis>
<methodsynopsis xml:id="object.unset">
<modifier>public</modifier> <type>void</type><methodname>__unset</methodname>
<methodparam><type>string</type><parameter>name</parameter></methodparam>
</methodsynopsis>
<para>
<link linkend="object.set">__set()</link> é executado ao escrever dados em
propriedades inacessíveis (private ou protected) ou propriedades inexistentes.
</para>
<para>
<link linkend="object.get">__get()</link> é utilizado para ler dados de propriedades
inacessíveis (private ou protected) ou propriedades inexistentes.
</para>
<para>
<link linkend="object.isset">__isset()</link> é disparado ao chamar a função
<function>isset</function> ou <function>empty</function>
em propriedades inacessíveis (private ou protected) ou propriedades inexistentes.
</para>
<para>
<link linkend="object.unset">__unset()</link> é invocado ao usar o construtor
<function>unset</function> em propriedades inacessíveis (private ou protected)
ou propriedades inexistentes.
</para>
<para>
O argumento <varname>$name</varname> é o nome da propriedade com o qual se está
interagindo. O argumento <varname>$value</varname> do método <link linkend="object.set">__set()</link>
especifica o valor para o qual a propriedade
<varname>$name</varname> deveria ser
definida.
</para>
<para>
A sobrecarga de propriedades funciona somente no contexto de objeto. Estes
métodos mágicos não são disparados em contexto estático. Portanto estes
métodos não podem ser declarados como
<link linkend="language.oop5.static">static</link>.
Um aviso é emitido se algum método mágico de sobrecarga
é declarado como <literal>static</literal>.
</para>
<note>
<para>
O valor de retorno de <link linkend="object.set">__set()</link> é ignorado
por causa da forma que o PHP processa o operador de atribuição.
Similarmente, o método <link linkend="object.get">__get()</link> nunca é chamado em
atribuições encadeadas como essa:
<literal><![CDATA[ $a = $obj->b = 8; ]]></literal>
</para>
</note>
<note>
<para>
O PHP não irá chamar métodos sobrecarregados a partir do próprio método sobrecarregado.
Isso significa, por exemplo, que escrever <code>return $this->foo</code> dentro de um
<link linkend="object.get">__get()</link> irá retornar <literal>null</literal>
e lançar um <constant>E_WARNING</constant> se não houver uma <literal>foo</literal> propriedade definida,
ao invés de chamar <link linkend="object.get">__get()</link> uma segunda vez.
Entretanto, métodos sobrecarregados podem invocar outros métodos sobrecarregados implicitamente (como um
<link linkend="object.set">__set()</link> chamando um <link linkend="object.get">__get()</link>).
</para>
</note>
<example>
<title>
Sobrecarregando propriedades com <link linkend="object.get">__get()</link>,
<link linkend="object.set">__set()</link>, <link linkend="object.isset">__isset()</link>
and <link linkend="object.unset">__unset()</link>
</title>
<programlisting role="php">
<![CDATA[
<?php
class PropertyTest
{
/** Local para dados sobrecarregados. */
private $data = array();
/** Sobrecarga não usada em propriedades declaradas. */
public $declared = 1;
/** Sobrecarga usada somente neste quando acessada fora da classe. */
private $hidden = 2;
public function __set($name, $value)
{
echo "Definindo '$name' para '$value'\n";
$this->data[$name] = $value;
}
public function __get($name)
{
echo "Obtendo '$name'\n";
if (array_key_exists($name, $this->data)) {
return $this->data[$name];
}
$trace = debug_backtrace();
trigger_error(
'Propriedade indefinida via __get(): ' . $name .
' em ' . $trace[0]['file'] .
' na linha ' . $trace[0]['line'],
E_USER_NOTICE);
return null;
}
public function __isset($name)
{
echo "'$name' está definido?\n";
return isset($this->data[$name]);
}
public function __unset($name)
{
echo "Removendo a definição de '$name'\n";
unset($this->data[$name]);
}
/** Não é um método mágico, está aqui somente para exemplo. */
public function getHidden()
{
return $this->hidden;
}
}
$obj = new PropertyTest;
$obj->a = 1;
echo $obj->a . "\n\n";
var_dump(isset($obj->a));
unset($obj->a);
var_dump(isset($obj->a));
echo "\n";
echo $obj->declared . "\n\n";
echo "Vamos experimentar com a propriedade privada chamada 'hidden':\n";
echo "Propriedades privadas são visíveis dentro da classe, por isso __get() não é usado...\n";
echo $obj->getHidden() . "\n";
echo "Propriedades privadas não são visíveis fora da classe, por isso __get() é usado...\n";
echo $obj->hidden . "\n";
?>
]]>
</programlisting>
&example.outputs;
<screen role="php">
<![CDATA[
Definindo 'a' to '1'
Obtendo 'a'
1
'a' está definido?
bool(true)
Removendo a definição de 'a'
'a' está definido?
bool(false)
1
Vamos experimentar com a propriedade privada chamada 'hidden':
Propriedades privadas são visíveis dentro da classe, por isso __get() não é usado...
2
Propriedades privadas não são visíveis fora da classe, por isso __get() é usado...
Obtendo 'hidden'
Notice: Propriedade indefinida via __get(): hidden em <file> na linha 70 em <file> na linha 29
]]>
</screen>
</example>
</sect2>
<sect2 xml:id="language.oop5.overloading.methods">
<title>Sobrecarga de método</title>
<methodsynopsis xml:id="object.call">
<modifier>public</modifier> <type>mixed</type><methodname>__call</methodname>
<methodparam><type>string</type><parameter>name</parameter></methodparam>
<methodparam><type>array</type><parameter>arguments</parameter></methodparam>
</methodsynopsis>
<methodsynopsis xml:id="object.callstatic">
<modifier>public static</modifier> <type>mixed</type><methodname>__callStatic</methodname>
<methodparam><type>string</type><parameter>name</parameter></methodparam>
<methodparam><type>array</type><parameter>arguments</parameter></methodparam>
</methodsynopsis>
<para>
<link linkend="object.call">__call()</link> é disparado ao invocar métodos
inacessíveis em um contexto de objeto.
</para>
<para>
<link linkend="object.callstatic">__callStatic()</link> é disparado quando invocando métodos
inacessíveis em um contexto estático.
</para>
<para>
O argumento <varname>$name</varname> é o nome do método sendo chamado. O
argumento <varname>$arguments</varname> é um array enumerado contendo os
parâmetros passados para o
método <varname>$name</varname>.
</para>
<example>
<title>
Sobrecarga de métodos instanciados com <link linkend="object.call">__call()</link>
e <link linkend="object.callstatic">__callStatic()</link>
</title>
<programlisting role="php">
<![CDATA[
<?php
class MethodTest
{
public function __call($name, $arguments)
{
// Observação: valor de $name é sensível a maiúsculas/minúsculas.
echo "Chamando método '$name' do objeto "
. implode(', ', $arguments). "\n";
}
public static function __callStatic($name, $arguments)
{
// Observação: valor de $name é sensível a maiúsculas/minúsculas.
echo "Chamando método '$name' estático "
. implode(', ', $arguments). "\n";
}
}
$obj = new MethodTest;
$obj->runTest('no contexto do objeto');
MethodTest::runTest('no contexto estático');
?>
]]>
</programlisting>
&example.outputs;
<screen role="php">
<![CDATA[
Chamando método 'runTest' do objeto no contexto do objeto
Chamando método 'runTest' estático no contexto estático
]]>
</screen>
</example>
</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
-->