117 lines
5.4 KiB
HTML
117 lines
5.4 KiB
HTML
<html>
|
||
|
||
<head>
|
||
<object type="application/x-oleobject" classid="clsid:1e2a7bd0-dab9-11d0-b93a-00c04fc99f9e">
|
||
<param name="Keyword" value="default">
|
||
<param name="Keyword" value="where">
|
||
</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 {
|
||
font-family: monospace;
|
||
font-size: 10pt;
|
||
color: #000080;
|
||
}
|
||
</style>
|
||
</head>
|
||
|
||
<body>
|
||
<H1><span lang="ru">Ограничения на параметры обобщенных подпрограмм и классов</span> </H1>
|
||
<p><span lang="ru">По умолчанию с переменными, имеющими тип параметра
|
||
обобщенного класса или подпрограммы, внутри методов обобщённых классов и
|
||
обобщенных подпрограмм можно делать лишь ограниченный набор действий:
|
||
присваивать и сравнивать на равенство </span>(<span lang="ru">отметим,
|
||
что в </span>NET <span lang="ru">сравнение на равенство внутри </span>обобщений<span lang="ru">
|
||
запрещено!).</span></p>
|
||
<p><span lang="ru">Например, данный код будет работать:</span></p>
|
||
<blockquote>
|
||
<p><code><b>function</b> Eq<T>(a,b: T): boolean;<br>
|
||
<b>begin</b><br>
|
||
Result := a = b;<br>
|
||
<b>end</b>;</code></p>
|
||
</blockquote>
|
||
<p><span lang="ru">Можно также использовать присваивание переменной, имеющей тип
|
||
параметра обобщенного класса или подпрограммы, значение по умолчанию, используя
|
||
конструкцию </span><code><b>default</b>(T)</code> - <span lang="ru">значение по
|
||
умолчанию для типа </span><code>T</code><span lang="ru"> (</span><code>nil</code>
|
||
<span lang="ru">для ссылочных типов и нулевое значение для размерных типов):</span></p>
|
||
<blockquote>
|
||
<p><code><b>procedure</b> Def<T>(<b>var</b> a: T);<br>
|
||
<b>begin</b><br>
|
||
a := <b>default</b>(T);<br>
|
||
<b>end</b>;</code></p>
|
||
</blockquote>
|
||
<p><span lang="ru">Однако, данный код </span>
|
||
</p>
|
||
<blockquote>
|
||
<p><code><b>function</b> Sum<T>(a,b: T): T;<br>
|
||
<b>begin</b><br>
|
||
Result := a + b;<br>
|
||
<b>end</b>;</code></p>
|
||
</blockquote>
|
||
<p><span lang="ru">вызовет ошибку компиляции до инстанцирования (создания
|
||
экземпляра с конкретным типом). Такое поведение в .</span>NET <span lang="ru">
|
||
кардинально отличается от шаблонов в </span>C++<span lang="ru">, где в коде
|
||
шаблона можно использовать любые операции с шаблонными параметрами, и ошибка
|
||
может произойти только в момент инстанцирования с конкретным типом.</span></p>
|
||
<p><span lang="ru">Чтобы разрешить использование некоторых действий с
|
||
переменными, имеющими тип параметра обобщенного класса или подпрограммы,
|
||
используются ограничения на
|
||
обобщенные параметры, задаваемые в секции </span><code><b>where</b></code>
|
||
<span lang="ru">после заголовка подпрограммы или класса:</span></p>
|
||
<blockquote>
|
||
<p><code><b>type</b><br>
|
||
<span lang="ru"> </span>MyPair<T> = <b>class<br>
|
||
</b><span lang="ru"> </span><b> where</b> T: System.ICloneable;<br>
|
||
<b> private<br>
|
||
</b>x,y: T;<b><br>
|
||
public<br>
|
||
constructor</b> (x,y: T);<br>
|
||
<b>begin</b><br>
|
||
Self.x := x;<br>
|
||
Self.y := y;<br>
|
||
<b>end</b>;<br>
|
||
<span lang="ru"> </span><b>function</b> Clone: MyPair;<br>
|
||
<span lang="ru"> </span><b>begin</b><br>
|
||
<span lang="ru"> </span>Result := new MyPair<T>(x.Clone,y.Clone);<br>
|
||
<span lang="ru"> </span><b>end</b>;<br>
|
||
<span lang="ru"> </span><b>end</b>;</code></p>
|
||
</blockquote>
|
||
<p><span lang="ru">В с</span>екци<span lang="ru">и</span> <code><b>where</b></code> <span lang="ru">
|
||
через запятую перечисляются </span>следующи<span lang="ru">е</span> ограничения:<br>
|
||
<span lang="ru">На </span>1 мест<span lang="ru">е</span>: слово <code><b>class</b></code>
|
||
<span lang="ru">или</span> слово <code><b>record</b></code> <span lang="ru">или</span> имя
|
||
<span lang="ru">класса-</span>предка<span lang="ru">.</span><br>
|
||
<span lang="ru">На </span>2 мест<span lang="ru">е</span>: список реализуемых интерфейсов<span lang="ru">
|
||
через запятую.</span><br>
|
||
<span lang="ru">На </span>3 мест<span lang="ru">е</span>: слово <strong>
|
||
<span class="auto-style1">constructor</span></strong>, указывающее, что данный тип должен иметь
|
||
конструктор по умолчанию. </p>
|
||
<p>При этом <span lang="ru">каждое</span> из
|
||
мест<span lang="ru">, кроме одного,</span> может <span lang="ru">быть пустым</span>. </p>
|
||
<p><span lang="ru">Для каждого типа-параметра может быть своя секция </span>
|
||
<strong><span class="auto-style1">where</span></strong><span lang="ru">, каждая секция </span>
|
||
<strong><span class="auto-style1">where</span></strong> <span lang="ru">завершается
|
||
точкой с запятой.</span></p>
|
||
<p><span lang="ru"><b>Пример.</b> Обобщенная функция поиска минимального
|
||
элемента в массиве. Элементы должны реализовывать интерфейс </span><code>
|
||
IComparable<T></code><span lang="ru">.</span></p>
|
||
<blockquote>
|
||
<p><code><b>function</b> MinElem<T>(a: <b>array</b> <b>of</b> T): T;<br>
|
||
<b>where</b> T: IComparable<T>;<br>
|
||
<b>begin</b><br>
|
||
<b>var</b> min := a[0];<br>
|
||
<b>for</b> <b>var</b> i := 1 <b>to</b> a.High <b>do</b><br>
|
||
<b>if</b> a[i].CompareTo(min)<0 <b>then</b><br>
|
||
min := a[i];<br>
|
||
Result := min; <br>
|
||
<b>end</b>; </code></p>
|
||
</blockquote>
|
||
<p><span lang="ru">К сожалению, нет возможности использовать запись a[i]</span><<span lang="ru">min,
|
||
поскольку операции не вход</span>я<span lang="ru">т в интерфейс</span>ы<span lang="ru">.</span></p>
|
||
</body>
|
||
|
||
</html>
|