pascalabcnet/PABCNetHelp/LangGuide/Classes/operoverloading.html
Mikhalkovich Stanislav 7aed6ed062 Print($'{Arr(1,2,3)}')
теперь печатает содержимое массива
2025-11-11 22:04:03 +03:00

153 lines
9.4 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<html>
<head>
<object type="application/x-oleobject" classid="clsid:1e2a7bd0-dab9-11d0-b93a-00c04fc99f9e">
<param name="Keyword" value="operator">
<param name="Keyword" value="implicit">
<param name="Keyword" value="explicit">
<param name="Keyword" value="Перегрузка операций">
</object>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
<title></title>
<link rel="StyleSheet" href="../../default.css">
<style type="text/css">
.auto-style1 {
color: #000080;
}
</style>
</head>
<body>
<H1>Перегрузка операций</H1>
<p>Перегрузка операций - это средство языка, позволяющее вводить
операции над типами, определяемыми пользователем. В <b>PascalABC.NET</b>
можно использовать только предопределенные значки операций.
Перегрузка операций для типа <code>T</code>, являющегося
классом или записью, осуществляется при помощи статической (классовой) функции-метода со
специальным именем <b><code>operator</code></b> <i>
ЗнакОперации</i>. Перегрузка специальных операций <code>+=</code>, <code>
-=</code>, <code>*=</code>, <code>/=</code>
осуществляется с помощью статической процедуры-метода, первый параметр
которой передается по ссылке.</p>
<p>Например:</p>
<blockquote>
<p><code><b>type</b> <br>&nbsp; Complex = <b>record</b><br>&nbsp;&nbsp;&nbsp; re,im: real;<br>&nbsp;&nbsp;&nbsp;
<strong>static</strong><b><span lang="en-us"> </span>function</b> <b>operator</b>+(a,b: Complex): Complex; <br>&nbsp;&nbsp;&nbsp;
<b>begin</b><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Result.re := a.re + b.re;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Result.im := a.im + b.im;
<br>&nbsp;&nbsp;&nbsp; <b>end</b>; <br>&nbsp;&nbsp;&nbsp;
<strong>static</strong><b><span lang="en-us"> </span>function</b> <b>operator</b>=(a,b: Complex): boolean; <br>&nbsp;&nbsp;&nbsp; <b>begin</b><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Result := (a.re = b.re)
<b>and</b> (a.im = b.im);<br>&nbsp;&nbsp;&nbsp; <b>end</b>; <br>&nbsp; <b>end</b>;</code></p>
</blockquote>
<p>Для перегрузки операций действуют следующие правила:</p>
<ol>
<li>Перегружать можно все операции за исключением
<code>@</code> (взятие адреса), <b><code>as</code></b>,
<code><b>is</b></code>, <code>new</code>. Кроме того,
можно перегружать специальные бинарные операции <code>+=</code>,
<code>-=</code>, <code>*=</code>, <code>/=</code>,
не возвращающие значений.</li>
<li>Перегружать можно только еще не перегруженные операции.</li>
<li>Тип по крайней мере одного операнда должен совпадать с
типом класса или записи, внутри которого определена операция.</li>
<li>Перегрузка осуществляется с помощью статической функции-метода,
количество параметров которой совпадает с количеством параметров
соответствующей операции (2 - для бинарной, 1 - для унарной).</li>
<li>Перегрузка операций <code>+=</code>, <code>-=</code>,
<code>*=</code>, <code>/=</code>
для соответствующих операторов
осуществляется с помощью статической процедуры-метода, первый параметр которой передается по
ссылке и имеет тип записи или класса, в котором определяется данная
операция, второй - передается по значению и совместим по присваиванию с
первым. Перегрузка остальных операций осуществляется с помощью статических
функций-методов. </li>
<li>Операции приведения типа <span lang="ru">задаются статическими
функциями, у которых </span>вместо имени <span lang="ru">используется </span>
<code><b>operator</b></code> <code><b>implicit</b></code> <span lang="ru">
(для неявного приведения типа) </span>и<span lang="ru">ли </span><code><b>
operator</b></code> <code><b>explicit</b></code> <span lang="ru">(для явного
приведения типа)</span>. </li>
</ol>
<p>Например:</p>
<blockquote>
<p><code><b>type</b> <br>&nbsp; Complex = <b>record</b><br>&nbsp;&nbsp;&nbsp;
...<br>&nbsp;&nbsp;&nbsp;
<strong>static</strong><b><span lang="en-us"> </span>function</b> <b>operator implicit</b>(d: real): Complex;<br>&nbsp;&nbsp;&nbsp;
<b>begin</b><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Result.re := d;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Result.im := 0;<br>&nbsp;&nbsp;&nbsp;
<b>end</b>; <br>&nbsp; &nbsp;
<strong>static</strong><b><span lang="en-us"> </span>function</b> <b>operator explicit</b>(c: Complex): string;<br>&nbsp;&nbsp;&nbsp;
<b>begin</b><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Result := Format('({0},{1})',c.re,c.im);<br>&nbsp;&nbsp;&nbsp;
<b>end</b>;<br>&nbsp;&nbsp;&nbsp;
<strong>static</strong><b><span lang="en-us"> </span>procedure</b> <b>operator</b>+=(<b>var</b> c: Complex;
value: Complex);<br>&nbsp;&nbsp;&nbsp; <b>begin</b><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
c.re += value.re;
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c.im += value.im;<br>&nbsp;&nbsp;&nbsp;
<b>end</b>;<br>&nbsp;&nbsp;&nbsp;
<strong>static</strong><span lang="en-us"><b> </b> </span><b>function</b> <b>operator</b>+(c,c1: Complex):
Complex;<br>&nbsp;&nbsp;&nbsp; <b>begin&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </b><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Result.re := c.re + c1.re;
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Result.im := c.im + c1.im;
<br>&nbsp;&nbsp;&nbsp;
<b>end</b>;<br>&nbsp; <b>end</b>;</code></p>
</blockquote>
<p>Можно перегружать операции с помощью <a href="extensionmethods.html">методов расширения</a> - в этом случае при
описании подпрограммы не следует писать слово static. Например, так в системном модуле
реализовано добавление числа к строке:</p>
<blockquote>
<p><code><strong>function</strong> <strong>operator</strong>+(str: string; n:
integer): string; <strong>extensionmethod</strong>;<br><strong>begin</strong><br>&nbsp;
Result := str +
n.ToString;<br><strong>end</strong>;</code></p>
</blockquote>
<p>При перегрузке операций методами расширения ключевое слово <code> <strong>extensionmethod</strong></code> можно не писать:</p>
<blockquote>
<p><code><strong>function</strong> <strong>operator</strong>+(str: string; n:
integer): string;<br><strong>begin</strong><br>&nbsp;
Result := str +
n.ToString;<br><strong>end</strong>;</code></p>
</blockquote>
<p>Можно перегружать расширенные операции присваивания +=, -= и т.д.: </p>
<blockquote>
<pre><code><strong>type</strong>
t0 = <strong>class
</strong> x: integer;
<strong>static</strong> <strong>function</strong> <strong>operator</strong>+=(a: t0; i: integer): t0;
<strong>begin</strong>
a.x += i;
<strong>end</strong>;
<strong>end</strong>;
<strong>begin</strong>
<strong>var</strong> t := new t0;
t += 2;
</code><span class="auto-style1"><font size="2"><strong>end</strong>.</font></span></pre>
</blockquote>
<p>Важно отметить, что если слева от расширенного присваивания находится
свойство, то перегруженная форма расширенного присваивания игнорируется и само
расширенное присваивание разворачивается в присваивание и соответствующую
операцию: </p>
<blockquote>
<pre><code><strong>type</strong>
t0 = <strong>class
</strong> x: integer;
<strong>static</strong> <strong>function</strong> <strong>operator</strong>+=(a: t0; i: integer): t0;
<strong>begin</strong>
a.x += i;
<strong>end</strong>;
<strong>end</strong>;
t1 = class
<strong>property</strong> p1: t0 <strong>read</strong> ...<strong> write</strong> ...;
<strong>end</strong>;
<strong>begin</strong>
<strong>var</strong> t := new t1;
t.p1 += 2;
</code><span class="auto-style1"><font size="2"><strong>end</strong>.</font></span></pre>
</blockquote>
<p>В данном коде последний оператор расширенного присваивания принудительно
развернется в </p>
<blockquote>
<pre><code>t.p1 := t.p1 + 2; </code></pre>
</blockquote>
<p>и поскольку для t0 не перегружена операция +, то компилятор выдаст ошибку.</p>
</body>
</html>