Статьи

Перегрузка операторов в AS3 с помощью редактора Realaxy

В предыдущем посте о Realaxy Editor мы говорили о языке черт, который позволяет использовать преимущества множественного наследования. Теперь мы переходим к другой заслуживающей внимания возможности: перегрузке операторов.

Realaxy ActionScript Editor (RASE) доступен здесь (для Windows, Macintosh OS X и Linux). Примечание: если вы впервые работаете с редактором, ознакомьтесь с инструкциями по RASE .

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

Преимущества операторов перегрузки очевидны:

  1. Компактный стиль. Ваши программы могут стать короче и более читабельными; например, гораздо проще использовать что-то вроде a*b*c чем a.multiply(b).multiply(с).
  2. Код часто выглядит более естественным. Четко определенный оператор легче понять и запомнить, чем имя функции и имя функции. Например, комбинируя две переменные типа Point, вы бы предпочли видеть что-то вроде point1 + point2, но не point1.plus(point2) .

Настоящим аргументом против перегрузки операторов является потеря контроля над вашим кодом. Иногда неясно, где оператор перегружен, а где нет. Добавление перегруженного оператора вызывает изменения в поведении существующего кода, которые могут привести к неожиданным последствиям.

Перегрузка оператора не включена в ActionScript (ECMA3), даже если она предлагается для стандарта ECMA4. Java не поддерживает перегрузку операторов, но есть и в Groovy («Java с синтаксическим сахаром»), и в Scala. Кроме того, операторы C # могут быть перегружены.

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

Мы говорим о языковом расширении overloadedOperators, которое появилось в RASE начиная с Beta 10 (сборка 8145+).

Простой способ импортировать его (или любой другой язык) в ваш проект — нажать Ctrl + L ( Cmd + L ) в Realaxy Editor.

Кстати, перегруженные операторы в RASE — это просто порт перегруженного языка Operators от платформы Jetbrains MPS. Мы просто решили не изобретать велосипед и, изучив предметную область приложения, пришли к выводу, что решение Jetbrains кажется достаточным и отвечает всем нашим потребностям. Мы добавили несколько небольших бонусов от нас.

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


Создайте новый проект с модулем внутри.


Назовите новый корень «операторы».


Добавьте код для тестирования в основной класс.

Здесь мы создали две переменные, p1 и p2 (тип Point). Теперь мы хотим получить третью переменную, p3, которая будет результатом объединения этих двух точек.

Выведите эти три значения: p1, p2, p3. Мы использовали values выражений из языковой logging , чтобы реализовать строковое сообщение для вывода на консоль.

Наш код вызывает сообщение об ошибке: «Операция не может быть применена к этим операндам». Компиляция невозможна.


Давайте объявим перегрузку оператора. Импортируйте com.realaxy.actionScript.overloadedOperators .


Добавьте новый корень « OverlodedOperatorsContainer »: щелкните правой кнопкой мыши узел пакета и выберите во всплывающем меню.


Назовите это « MyOperators ».

Здесь мы видим два блока объявлений: « overloaded binary operators » и « custom operators declarations ».


Перейти к первому блоку и нажать Enter . Добавлено новое объявление оператора.


Выберите оператор « + ». Выберите тип Point для обеих сторон. Установите возвращаемое значение Point (измените его со значения по умолчанию « void »).

Теперь мы можем добавить код, который будет выполняться при объединении Point с Point (используя оператор « + »).

Это все.

Красная подсветка, указывающая на ошибку в нашем классе, исчезла.


Начните компиляцию.


Создайте конфигурацию запуска для нашего модуля.


Назначьте основной класс (если вы не сделали этого раньше).


Мы получаем следующее сообщение на консоли:


Теперь давайте попробуем выполнить чуть более сложную задачу и переопределить операции вычитания, умножения и деления. Для Number и Point .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
operator + (Point, Point) -> Point
commutative: false
(left, right)->Point {
  return new Point(left.x + right.x, left.y + right.y);
}
 
operator + (Point, Number) -> Point
commutative: false
(left, right)->Point {
  return new Point(left.x + right, left.y + right);
}
 
operator — (Point, Point) -> Point
commutative: false
(left, right)->Point {
  return new Point(left.x — right.x, left.y — right.y);
}
 
operator — (Point, Number) -> Point
commutative: false
(left, right)->Point {
  return new Point(left.x — right, left.y — right);
}
 
operator * (Point, Point) -> Point
commutative: false
(left, right)->Point {
  return new Point(left.x * right.x, left.y * right.y);
}
 
operator * (Point, Number) -> Point
commutative: false
(left, right)->Point {
  return new Point(left.x * right, left.y * right);
}
 
operator / (Point, Point) -> Point
commutative: false
(left, right)->Point {
  return new Point(left.x / right.x, left.y / right.y);
}
 
operator / (Point, Number) -> Point
commutative: false
(left, right)->Point {
  return new Point(left.x / right, left.y / right);
}

Представьте, что вам нужно вычислить точку, которая расположена слева и вниз на 50 пикселей от центра расстояния между двумя точками.

Это просто:

Или даже проще:

Но не забывайте, что в реальной жизни Flasher это было бы так:

Сравните эти цифры. Это достаточно веская причина для использования перегрузки операторов в проектах ActionScript.


Теперь давайте узнаем, как создавать собственные операторы.

Сначала вернитесь к объявлению MyOperators и перейдите к custom operators declarations .

Нажмите Enter, чтобы создать новую декларацию. Визуальное представление будет ~= .


Наш пользовательский оператор должен проверить строку на соответствие регулярному выражению. Чтобы описать такое поведение оператора, мы добавляем новую перегрузку, как мы это делали 10 минут назад с помощью Point . Единственное отличие заключается в добавлении ~= для автозаполнения.

Левый операнд должен взять String , а правый — RegExp . Возвращаемое значение должно быть Boolean .

Затем добавьте некоторый код, который будет выполняться нашим оператором, вызывая метод test из значения.


Создайте тестовую операцию в Main () чтобы увидеть, как она работает:

Быстро и просто.

Чтобы избежать путаницы во всех этих пользовательских операторах, вы должны запомнить одну комбинацию клавиш, связанную с навигацией: Ctrl-B (или Ctrl + щелчок по оператору) приведет вас к объявлению оператора.

Полезный совет: чтобы отличить перезагруженный оператор от встроенного, наведите на него курсор мыши и нажмите Ctrl .

Конечно, если вы на Mac, используйте Cmd вместо Ctrl.


Давайте расширим поведение нашего пользовательского оператора с помощью новой функции — коммутативности .

Выберите оператора и нажмите Alt-Enter . Выберите Flip Binary Operation во всплывающем меню. Это поменяет обе стороны, однако с сообщением об ошибке, потому что оператор ~= еще не определен для таких операндов.

Перейдите к декларации операторов. Установите commutative = true . Красная подсветка ошибки должна исчезнуть (иногда вы должны нажать F5, чтобы обновить вид).

Другими словами, эта « commutative » установка является старым добрым правилом, согласно которому изменение порядка слагаемых не меняет сумму. Теперь наш оператор ~= будет работать, если мы поместим RegExp перед строкой.

Гуру ООП предостерегают от злоупотребления этим поведением. Иногда это связано с неожиданными последствиями. Давайте поверим в это и запомним это.

Это все, что нужно сделать. У нас есть перегрузка операторов в ActionScript 3.