Типы операторов — различия между версиями

Материал из Deeptown Manual
Перейти к: навигация, поиск
(Web Sales Pages, http://byclloaybs.blog.mongenie.com/index/p/2012/05/1591008 Electronic Cigarette Starter Kit E-Lites, 502401, http://avkbudbte.blog.mongenie.com/index/p/2012/05/1609642 Memorial Day)
 
(не показаны 858 промежуточных версий 32 участников)
Строка 1: Строка 1:
Web Sales Pages, http://byclloaybs.blog.mongenie.com/index/p/2012/05/1591008 Electronic Cigarette Starter Kit E-Lites, 502401, http://avkbudbte.blog.mongenie.com/index/p/2012/05/1609642 Memorial Day Weekend 2010 Colorado Springs, vtu, http://goeesritukm.blogtrue.com/article/5349554/Lala-Vasquez-Before-Surgery Lala Vasquez Before Surgery, ecwm, http://mfxkqbxeqmlt.blogtrue.com/article/5327790/Memorial-Day-2010-Fireworks-Nyc Memorial Day 2010 Fireworks Nyc,  874, http://fqpowknygqaba.blogtrue.com/article/5299562/Pittsburgh-Memorial-Day-Weekend-2011 Pittsburgh Memorial Day Weekend 2011,  26155, http://ibqeceyd.blog.mongenie.com/index/p/2012/05/1610179 Titanic 3D Until When Cinemark,  >:OOO, http://pftqmrotjx.blog.mongenie.com/index/p/2012/05/1597011 Father's Day 2010 Penang, xhkm, http://kytiasanix.blogage.de/entries/2012/5/18/Which-E-Cigarette-Is-Best-Juice Which E Cigarette Is Best Juice, 786, http://blogshells.com/dxyzqrcc/2012/05/18/e_cigarette_forum_mods/ E Cigarette Forum Mods, 21648, http://blogshells.com/mjomalaa/2012/05/18/kqrs_memorial_day_countdown/ Kqrs Memorial Day Countdown, dzm, http://blogshells.com/micpusugs/2012/05/18/father_day_quotes_in_urdu/ Father Day Quotes In Urdu, 29190, http://lvlrprtlph.blogtrue.com/article/5317919/Memorial-Day-2011-Fireworks-New-York Memorial Day 2011 Fireworks New York, nho, http://blogshells.com/tffnmjoj/2012/05/18/father's_day_diy/ Father's Day Diy, ysmdc, http://kjgxcqtgfwavt.blogtrue.com/article/5308986/Electronic-Cigarette-Safety-Reviews-Liquid Electronic Cigarette Safety Reviews Liquid,  cqlwym, http://jccqnkvjdw.blog.mongenie.com/index/p/2012/05/1591196 E Cigarette Charger And Cartridge,  ick, http://blogshells.com/rnzyxooqwl/2012/05/18/what_to_do_on_father's_day_ontario/ What To Do On Father's Day Ontario, 806, http://odgqqnqjne.blog.mongenie.com/index/p/2012/05/1599526 E Cigarette Where To Buy York City, %-)), http://megxrikp.blog.mongenie.com/index/p/2012/05/1592559 Olympic Games London 2012 Closing Ceremony,  cwolvz, http://gjqeghzj.blog.mongenie.com/index/p/2012/05/1609068 Titanic 3D Experience Premiere,  lfpz, http://hiyvrjtvuq.lefora.com/2012/05/18/buy-e-cigarette-starter-kit/ Buy E Cigarette Starter Kit, :(((, http://nescmmse.blog.mongenie.com/index/p/2012/05/1610183 Memorial Day Party Ucla,  8-], http://bdyyrytpm.blogage.de/entries/2012/5/17/Videos-De-Jeny-Ribera Videos De Jeny Ribera8OO, http://vgmiwskeojtvmo.blogtrue.com/article/5277780/Painful-Blisters-Between-Toes Painful Blisters Between Toes, 8))), http://wowrvejagn.blogage.de/entries/2012/5/17/Are-E-Cigarettes-Banned-In-Canada Are E Cigarettes Banned In Canada,  gtmgba,
+
Операторы отличаются от обычных функций тем, что имеют определенные ограничения по количеству
 +
аргументов, а также некоторое ожидаемое поведение. Например, оператор + (сложение), принимающий
 +
более чем один аргумент, выглядел бы глупо. Кроме того, вряд ли кто-то ждет от оператора сложения
 +
изменение объекта, для которого он вызван, или аргумента.
 +
 
 +
Рассмотрим различные типы операторов более подробно.
 +
 
 +
== Арифметические ==
 +
 
 +
К этому типу относятся следующие операторы:
 +
* <tt>+</tt>, <tt>-</tt>, <tt>*</tt>, <tt>/</tt>, <tt>%</tt>
 +
* бинарный сдвиг: <tt><<</tt>, <tt>>></tt>
 +
* бинарная логика: <tt>|</tt> (или), <tt>&</tt> (и), <tt>^</tt> (исключающее или), <tt>~</tt> (не)
 +
* инкремент и декремент: <tt>++</tt>, <tt>--</tt>
 +
 
 +
Все арифметические операторы, за исключением бираного НЕ, инкремента и декремента, принимают
 +
один параметр. Они не должны менять исходный объект и объект-параметр; результат операции
 +
должен быть возвращен в виде вновь созданного объекта. Таким образом, и оператор и его аргумент
 +
должны быть объявлены константными.
 +
 
 +
В качестве примера приведем реализацию некоторых операторов для класса двумерного вектора:
 +
 
 +
<source lang="kpp">
 +
class Vector2 {
 +
    var real m_x, real m_y;    // координаты
 +
public:
 +
    property real x read m_x write m_x;
 +
    property real y read m_y write m_y;
 +
 
 +
    // конструктор для упрощения создания объекта
 +
    constructor create(const real X, const real Y)
 +
    {
 +
        var self = new Vector2;
 +
        self.m_x = X;
 +
        self.m_y = Y;
 +
        return self;
 +
    }
 +
 
 +
    // операторы сложения и скалярного произведения векторов:
 +
    const operator Vector2 + (const Vector2 arg)
 +
    {
 +
        // возвращаем новый объект в качестве результата!
 +
        return Vector2.create(x + arg.x, y + arg.y);
 +
    }
 +
 
 +
    const operator real * (const Vector2 arg)
 +
    {
 +
        // скалярное произведение
 +
        return x * arg.x + y * arg.y;
 +
    }
 +
};
 +
</source>
 +
 
 +
 
 +
== Операторы сравнения ==
 +
 
 +
Существует 6 операторов сравнения: "меньше", "больше", "меньше или равно", "больше или равно", "равно" и "не равно" -
 +
соответственно, <tt><</tt>, <tt>></tt>, <tt><=</tt>, <tt>>=</tt>, <tt>==</tt>, <tt>!=</tt>.
 +
 
 +
Все эти операторы также должны принимать один параметр, не должны изменять объект и параметр, а кроме того, все они
 +
должны возвращать в качестве результата логическое значение - true или false.
 +
 
 +
'''Примечание:''' в стандартной библиотеке языка K++ объявлен класс-[[примесь]] [[Comparable]], который упрощает реализацию
 +
этих операторов.
 +
 
 +
Достаточно унаследовать свой класс от [[Comparable]] и определить в классе метод <tt>compare</tt>, который принимает один
 +
аргумент и возвращает значение
 +
* меньшее нуля, если объект меньше аргумента;
 +
* равное нулю, если объект равен аргументу;
 +
* большее нуля, если объект больше аргумента.
 +
 
 +
Все остальные операторы, а также метод <tt>between</tt>, определены в [[Comparable]].
 +
 
 +
== Операторы присваивания ==
 +
 
 +
Оператор присваивания <tt>=</tt> - это оператор, который копирует значение своего аргумента в текущий объект.
 +
 
 +
Кроме того, каждому арифметическому оператору соответствует оператор присваивания, имя которого составляется из
 +
имени математического оператора плюс символ "=" (например, <tt>+=</tt>). Такие операторы делают соответствующее
 +
математическое действие с текущим объектом.
 +
 
 +
Операторы присваивания изменяют текущий объект, но не изменяют аргумент. Все они, кроме <tt>~=</tt>, <tt>--=</tt>
 +
и <tt>++=</tt>, принимают ровно один аргумент.
 +
 
 +
Операторы присваивания должны возвращать текущий объект в качестве результата.
 +
 
 +
Операторы <tt>--=</tt> и <tt>++=</tt> соответствуют префиксному инкременту и декременту.
 +
 
 +
Для того же класса <tt>Vector2</tt> из предыдущего примера:
 +
 
 +
<source lang="kpp">
 +
    operator Vector2 += (const Vector2 arg)
 +
    {
 +
        x += arg.x;
 +
        y += arg.y;
 +
        return this;
 +
    }
 +
</source>
 +
 
 +
 
 +
== Операторы приведения типов ==
 +
 
 +
Часто бывает так, что одни и те же объекты могут быть представлены различными способами. Например, число 5 может
 +
быть представлено как целочисленное 5, вещественное 5.0 или в виде строки "5".
 +
 
 +
Операторы приведения типов позволяют преобразовывать объекты из одних классов в другие.
 +
 
 +
Имя такого оператора совпадает с именем класса, в который производится преобразование; оператор не принимает
 +
параметров и не должен менять текущий объект.
 +
 
 +
При объявлении оператора приведения типа, тип результата функции указывать не следует.
 +
 
 +
Продолжим пример с двумерным вектором. В некоторых задачах бывает целесообразно определить преобразование вектора
 +
в вещественное число, возвращающее длину вектора.
 +
Это можно сделать следующим образом:
 +
 
 +
<source lang="kpp">
 +
    const operator real ()
 +
    {
 +
        return sqrt( x * x + y * y );
 +
    }
 +
 
 +
// В коде:
 +
var v = Vector2.create(3.0, 4.0);
 +
var len = v as real; // => 5.0
 +
</source>
 +
 
 +
 
 +
== Оператор индексного доступа ==
 +
 
 +
Существует два оператора - <tt>[]</tt> и <tt>[]=</tt> - оператор индексного чтения и оператор индексной записи.
 +
 
 +
Оператор индексного чтения принимает не менее одного параметра (возможно более одного), не меняет объект и параметры
 +
и должен возвращать значение - значение элемента по указанным индексам.
 +
 
 +
Оператор индексной записи принимает не менее двух параметров. Последний параметр всегда соответствует значению, которое
 +
должно быть записано. Оператор изменяет объект, но не изменяет свои параметры.
 +
 
 +
Для двумерного вектора может быть удобным проиндексировать координаты. В этом случае можно определить следующие операторы:
 +
 
 +
<source lang="kpp">
 +
    const operator real [] (const int idx)
 +
    {
 +
        switch(idx) {
 +
            case 0: return x;
 +
            case 1: return y;
 +
            default: throw ERangeError.create('index is out of range');
 +
        }
 +
    }
 +
 
 +
    const operator Vector2 []= (const int idx, const real value)
 +
    {
 +
        switch(idx) {
 +
            case 0: x = value;
 +
            case 1: y = value;
 +
            default: throw ERangeError.create('index is out of range');
 +
        }
 +
    }
 +
 
 +
// В коде:
 +
var v = Vector2.create(0, 0);
 +
v[1] = 5;      // => (0, 5)
 +
var r = v[0]; // => 0
 +
</source>
 +
 
 +
 
 +
== Оператор вызова функции ==
 +
 
 +
Специальный оператор <tt>call</tt> используется для того, чтобы объект можно было бы использовать как функцию.
 +
Нет никаких ограничений на параметры и поведение этого оператора.
 +
 
 +
Пример:
 +
 
 +
<source lang="kpp">
 +
class GreetingPrinter {
 +
    public operator call (const string who)
 +
    {
 +
        puts("Hello, #{who}!");
 +
    }
 +
}
 +
 
 +
// Использование:
 +
var greeting = new GreetingPrinter;
 +
greeting("Peter");  // выведет "Hello, Peter!"
 +
 
 +
function f(const b)
 +
{
 +
    b("Vova");
 +
}
 +
 
 +
f() { |x| puts("Hi, #{x}!"); };  // выведет "Hi, Vova!"
 +
f(new GreetingPrinter);          // выведет "Hello, Vova!"
 +
</source>

Текущая версия на 15:23, 13 июля 2013

Операторы отличаются от обычных функций тем, что имеют определенные ограничения по количеству аргументов, а также некоторое ожидаемое поведение. Например, оператор + (сложение), принимающий более чем один аргумент, выглядел бы глупо. Кроме того, вряд ли кто-то ждет от оператора сложения изменение объекта, для которого он вызван, или аргумента.

Рассмотрим различные типы операторов более подробно.

Содержание

[править] Арифметические

К этому типу относятся следующие операторы:

  • +, -, *, /, %
  • бинарный сдвиг: <<, >>
  • бинарная логика: | (или), & (и), ^ (исключающее или), ~ (не)
  • инкремент и декремент: ++, --

Все арифметические операторы, за исключением бираного НЕ, инкремента и декремента, принимают один параметр. Они не должны менять исходный объект и объект-параметр; результат операции должен быть возвращен в виде вновь созданного объекта. Таким образом, и оператор и его аргумент должны быть объявлены константными.

В качестве примера приведем реализацию некоторых операторов для класса двумерного вектора:

<source lang="kpp"> class Vector2 {

   var real m_x, real m_y;    // координаты

public:

   property real x read m_x write m_x;
   property real y read m_y write m_y;
   // конструктор для упрощения создания объекта
   constructor create(const real X, const real Y)
   {
       var self = new Vector2;
       self.m_x = X;
       self.m_y = Y;
       return self;
   }
   // операторы сложения и скалярного произведения векторов:
   const operator Vector2 + (const Vector2 arg)
   {
       // возвращаем новый объект в качестве результата!
       return Vector2.create(x + arg.x, y + arg.y);
   }
   const operator real * (const Vector2 arg)
   {
       // скалярное произведение
       return x * arg.x + y * arg.y;
   }

}; </source>


[править] Операторы сравнения

Существует 6 операторов сравнения: "меньше", "больше", "меньше или равно", "больше или равно", "равно" и "не равно" - соответственно, <, >, <=, >=, ==, !=.

Все эти операторы также должны принимать один параметр, не должны изменять объект и параметр, а кроме того, все они должны возвращать в качестве результата логическое значение - true или false.

Примечание: в стандартной библиотеке языка K++ объявлен класс-примесь Comparable, который упрощает реализацию этих операторов.

Достаточно унаследовать свой класс от Comparable и определить в классе метод compare, который принимает один аргумент и возвращает значение

  • меньшее нуля, если объект меньше аргумента;
  • равное нулю, если объект равен аргументу;
  • большее нуля, если объект больше аргумента.

Все остальные операторы, а также метод between, определены в Comparable.

[править] Операторы присваивания

Оператор присваивания = - это оператор, который копирует значение своего аргумента в текущий объект.

Кроме того, каждому арифметическому оператору соответствует оператор присваивания, имя которого составляется из имени математического оператора плюс символ "=" (например, +=). Такие операторы делают соответствующее математическое действие с текущим объектом.

Операторы присваивания изменяют текущий объект, но не изменяют аргумент. Все они, кроме ~=, --= и ++=, принимают ровно один аргумент.

Операторы присваивания должны возвращать текущий объект в качестве результата.

Операторы --= и ++= соответствуют префиксному инкременту и декременту.

Для того же класса Vector2 из предыдущего примера:

<source lang="kpp">

   operator Vector2 += (const Vector2 arg)
   {
       x += arg.x;
       y += arg.y;
       return this;
   }

</source>


[править] Операторы приведения типов

Часто бывает так, что одни и те же объекты могут быть представлены различными способами. Например, число 5 может быть представлено как целочисленное 5, вещественное 5.0 или в виде строки "5".

Операторы приведения типов позволяют преобразовывать объекты из одних классов в другие.

Имя такого оператора совпадает с именем класса, в который производится преобразование; оператор не принимает параметров и не должен менять текущий объект.

При объявлении оператора приведения типа, тип результата функции указывать не следует.

Продолжим пример с двумерным вектором. В некоторых задачах бывает целесообразно определить преобразование вектора в вещественное число, возвращающее длину вектора. Это можно сделать следующим образом:

<source lang="kpp">

   const operator real ()
   {
       return sqrt( x * x + y * y );
   }

// В коде: var v = Vector2.create(3.0, 4.0); var len = v as real; // => 5.0 </source>


[править] Оператор индексного доступа

Существует два оператора - [] и []= - оператор индексного чтения и оператор индексной записи.

Оператор индексного чтения принимает не менее одного параметра (возможно более одного), не меняет объект и параметры и должен возвращать значение - значение элемента по указанным индексам.

Оператор индексной записи принимает не менее двух параметров. Последний параметр всегда соответствует значению, которое должно быть записано. Оператор изменяет объект, но не изменяет свои параметры.

Для двумерного вектора может быть удобным проиндексировать координаты. В этом случае можно определить следующие операторы:

<source lang="kpp">

   const operator real [] (const int idx)
   {
       switch(idx) {
           case 0: return x;
           case 1: return y;
           default: throw ERangeError.create('index is out of range');
       }
   }
   const operator Vector2 []= (const int idx, const real value)
   {
       switch(idx) {
           case 0: x = value;
           case 1: y = value;
           default: throw ERangeError.create('index is out of range');
       }
   }

// В коде: var v = Vector2.create(0, 0); v[1] = 5; // => (0, 5) var r = v[0]; // => 0 </source>


[править] Оператор вызова функции

Специальный оператор call используется для того, чтобы объект можно было бы использовать как функцию. Нет никаких ограничений на параметры и поведение этого оператора.

Пример:

<source lang="kpp"> class GreetingPrinter {

   public operator call (const string who)
   {
       puts("Hello, #{who}!");
   }

}

// Использование: var greeting = new GreetingPrinter; greeting("Peter"); // выведет "Hello, Peter!"

function f(const b) {

   b("Vova");

}

f() { |x| puts("Hi, #{x}!"); }; // выведет "Hi, Vova!" f(new GreetingPrinter); // выведет "Hello, Vova!" </source>

Персональные инструменты
Пространства имён

Варианты
Действия
Навигация
информация
документация
Инструменты