mirror of
https://github.com/php/doc-ru.git
synced 2026-03-24 07:42:22 +01:00
325 lines
13 KiB
XML
325 lines
13 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
||
<!-- EN-Revision: d6f54016d62904cfd8200604aadd5e3f0d9bad97 Maintainer: shein Status: ready -->
|
||
<!-- Reviewed: no -->
|
||
<sect1 xml:id="language.oop5.overloading" xmlns="http://docbook.org/ns/docbook">
|
||
<title>Перегрузка</title>
|
||
|
||
<para>
|
||
Перегрузка в PHP означает возможность динамически <quote>создавать</quote>
|
||
свойства и методы. Эти динамические сущности обрабатываются с
|
||
помощью магических методов, которые можно создать в классе для
|
||
различных видов действий.
|
||
</para>
|
||
|
||
<para>
|
||
Методы перегрузки вызываются при взаимодействии со свойствами
|
||
или методами, которые не были объявлены или не <link
|
||
linkend="language.oop5.visibility">видны</link> в текущей области
|
||
видимости. Далее в этом разделе будут использоваться термины
|
||
<quote>недоступные свойства</quote> или <quote>недоступные методы</quote>
|
||
для обозначения этой комбинации объявления и области видимости.
|
||
</para>
|
||
|
||
<para>
|
||
Все методы перегрузки должны быть объявлены как <literal>public</literal>.
|
||
</para>
|
||
|
||
<note>
|
||
<para>
|
||
Ни один из аргументов этих магических методов не может быть передан
|
||
<link linkend="functions.arguments.by-reference">по ссылке</link>.
|
||
</para>
|
||
</note>
|
||
|
||
<note>
|
||
<para>
|
||
Интерпретация <quote>перегрузки</quote> в PHP отличается
|
||
от большинства объектно-ориентированных языков. Традиционно
|
||
перегрузка означает возможность иметь несколько одноимённых методов
|
||
с разным количеством и типами аргументов.
|
||
</para>
|
||
</note>
|
||
|
||
<sect2 xml:id="language.oop5.overloading.members">
|
||
<title>Перегрузка свойств</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> будет выполнен при записи
|
||
данных в недоступные (защищённые или приватные) или несуществующие свойства.
|
||
</para>
|
||
|
||
<para>
|
||
Метод <link linkend="object.get">__get()</link> будет выполнен при чтении
|
||
данных из недоступных (защищённых или приватных) или несуществующих свойств.
|
||
</para>
|
||
|
||
<para>
|
||
Метод <link linkend="object.isset">__isset()</link> будет выполнен при
|
||
использовании <function>isset</function> или <function>empty</function>
|
||
на недоступных (защищённых или приватных) или несуществующих свойствах.
|
||
</para>
|
||
|
||
<para>
|
||
Метод <link linkend="object.unset">__unset()</link> будет выполнен при вызове
|
||
<function>unset</function> на недоступном (защищённом или приватном) или несуществующем свойстве.
|
||
</para>
|
||
|
||
<para>
|
||
Аргумент <varname>$name</varname> представляет собой имя
|
||
вызываемого свойства. Метод <link linkend="object.set">__set()</link>
|
||
содержит аргумент <varname>$value</varname>, представляющий
|
||
собой значение, которое будет записано в свойство с именем
|
||
<varname>$name</varname>.
|
||
</para>
|
||
|
||
<para>
|
||
Перегрузка свойств работает только в контексте объекта.
|
||
Данные магические методы не будут вызваны в статическом контексте.
|
||
Поэтому эти методы не должны объявляться
|
||
<link linkend="language.oop5.static">статическими</link>.
|
||
При объявлении любого магического метода как
|
||
<literal>static</literal> будет выдано предупреждение.
|
||
</para>
|
||
|
||
<note>
|
||
<para>
|
||
Возвращаемое значение <link linkend="object.set">__set()</link> будет
|
||
проигнорировано из-за способа обработки в PHP оператора присваивания.
|
||
Аналогично, <link linkend="object.get">__get()</link> никогда не вызывается при
|
||
объединении присваиваний, например, подобным образом:
|
||
<literal><![CDATA[ $a = $obj->b = 8;]]></literal>
|
||
</para>
|
||
</note>
|
||
|
||
<note>
|
||
<para>
|
||
PHP не будет вызывать перегруженный метод изнутри того же перегруженного метода.
|
||
Это означает, что, например, написание <code>return $this->foo</code> внутри
|
||
<link linkend="object.get">__get()</link> вернёт <literal>null</literal>
|
||
и вызовет ошибку уровня <constant>E_WARNING</constant>, если не определено свойство <literal>foo</literal>,
|
||
вместо того, чтобы вызвать метод <link linkend="object.get">__get()</link> во второй раз.
|
||
Однако методы перегрузки могут неявно вызывать другие методы перегрузки (например,
|
||
метод <link linkend="object.set">__set()</link> вызывает метод <link linkend="object.get">__get()</link>).
|
||
</para>
|
||
</note>
|
||
|
||
<example>
|
||
<title>
|
||
Перегрузка свойств с помощью методов <link linkend="object.get">__get()</link>,
|
||
<link linkend="object.set">__set()</link>, <link linkend="object.isset">__isset()</link>
|
||
и <link linkend="object.unset">__unset()</link>
|
||
</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
class PropertyTest
|
||
{
|
||
/** Место хранения перегружаемых данных. */
|
||
private $data = array();
|
||
|
||
/** Перегрузка не применяется к объявленным свойствам. */
|
||
public $declared = 1;
|
||
|
||
/** Здесь перегрузка будет использована только при доступе вне класса. */
|
||
private $hidden = 2;
|
||
|
||
public function __set($name, $value)
|
||
{
|
||
echo "Установка '$name' в '$value'\n";
|
||
$this->data[$name] = $value;
|
||
}
|
||
|
||
public function __get($name)
|
||
{
|
||
echo "Получение '$name'\n";
|
||
if (array_key_exists($name, $this->data)) {
|
||
return $this->data[$name];
|
||
}
|
||
|
||
$trace = debug_backtrace();
|
||
trigger_error(
|
||
'Неопределённое свойство в __get(): ' . $name .
|
||
' в файле ' . $trace[0]['file'] .
|
||
' на строке ' . $trace[0]['line'],
|
||
E_USER_NOTICE);
|
||
return null;
|
||
}
|
||
|
||
public function __isset($name)
|
||
{
|
||
echo "Установлено ли '$name'?\n";
|
||
return isset($this->data[$name]);
|
||
}
|
||
|
||
public function __unset($name)
|
||
{
|
||
echo "Уничтожение '$name'\n";
|
||
unset($this->data[$name]);
|
||
}
|
||
|
||
/** Не магический метод, просто для примера. */
|
||
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 "Давайте поэкспериментируем с закрытым свойством 'hidden':\n";
|
||
echo "Закрытые свойства видны внутри класса, поэтому __get() не используется...\n";
|
||
echo $obj->getHidden() . "\n";
|
||
echo "Закрытые свойства не видны вне класса, поэтому __get() используется...\n";
|
||
echo $obj->hidden . "\n";
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
&example.outputs;
|
||
<screen role="php">
|
||
<![CDATA[
|
||
Установка 'a' в '1'
|
||
Получение 'a'
|
||
1
|
||
|
||
Установлено ли 'a'?
|
||
bool(true)
|
||
Уничтожение 'a'
|
||
Установлено ли 'a'?
|
||
bool(false)
|
||
|
||
1
|
||
|
||
Давайте поэкспериментируем с закрытым свойством 'hidden':
|
||
Закрытые свойства видны внутри класса, поэтому __get() не используется...
|
||
2
|
||
Закрытые свойства не видны вне класса, поэтому __get() используется...
|
||
Получение 'hidden'
|
||
|
||
|
||
Notice: Неопределённое свойство в __get(): hidden в <file> on line 70 in <file> on line 29
|
||
]]>
|
||
</screen>
|
||
|
||
</example>
|
||
</sect2>
|
||
|
||
<sect2 xml:id="language.oop5.overloading.methods">
|
||
<title>Перегрузка методов</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> запускается при вызове
|
||
недоступных методов в контексте объект.
|
||
</para>
|
||
|
||
<para>
|
||
<link linkend="object.callstatic">__callStatic()</link> запускается
|
||
при вызове недоступных методов в статическом контексте.
|
||
</para>
|
||
|
||
<para>
|
||
Аргумент <varname>$name</varname> представляет собой имя
|
||
вызываемого метода. Аргумент <varname>$arguments</varname>
|
||
представляет собой нумерованный массив, содержащий параметры,
|
||
переданные в вызываемый метод <varname>$name</varname>.
|
||
</para>
|
||
|
||
<example>
|
||
<title>
|
||
Перегрузка методов с помощью методов <link linkend="object.call">__call()</link>
|
||
и <link linkend="object.callstatic">__callStatic()</link>
|
||
</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
class MethodTest {
|
||
public function __call($name, $arguments) {
|
||
// Замечание: значение $name регистрозависимо.
|
||
echo "Вызов метода '$name' "
|
||
. implode(', ', $arguments). "\n";
|
||
}
|
||
|
||
public static function __callStatic($name, $arguments) {
|
||
// Замечание: значение $name регистрозависимо.
|
||
echo "Вызов статического метода '$name' "
|
||
. implode(', ', $arguments). "\n";
|
||
}
|
||
}
|
||
|
||
$obj = new MethodTest;
|
||
$obj->runTest('в контексте объекта');
|
||
|
||
MethodTest::runTest('в статическом контексте');
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
&example.outputs;
|
||
<screen role="php">
|
||
<![CDATA[
|
||
Вызов метода 'runTest' в контексте объекта
|
||
Вызов статического метода 'runTest' в статическом контексте
|
||
]]>
|
||
</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
|
||
-->
|