//////////////////////////////////////////

  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an
  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  KIND, either express or implied.  See the License for the
  specific language governing permissions and limitations
  under the License.

//////////////////////////////////////////

[[groovy-operators]]
= Operators

This chapter covers the operators of the Groovy programming language.

== Arithmetic operators

Groovy supports the usual familiar arithmetic operators you find in mathematics and in other programming languages like Java.
All the Java arithmetic operators are supported. Let's go through them in the following examples.

=== Normal arithmetic operators

The following binary arithmetic operators are available in Groovy:

[cols="1,1,1" options="header"]
|====
| Operator
| Purpose
| Remarks

| `+`
| addition
|

| `-`
| subtraction
|

| `*`
| multiplication
|

| `/`
| division
| Use `intdiv()` for integer division, and see the section about <<core-syntax.adoc#integer_division,integer division>> for more information on the return type of the division.

| `%`
| remainder
|

| `**`
| power
| See the section about <<core-syntax.adoc#power_operator,the power operation>> for more information on the return type of the operation.
|====

Here are a few examples of usage of those operators:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=binary_arith_ops,indent=0]
----

=== Unary operators

The `+` and `-` operators are also available as unary operators:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=unary_plus_minus,indent=0]
----
<1> Note the usage of parentheses to surround an expression to apply the unary minus to that surrounded expression.

In terms of unary arithmetics operators, the `++` (increment) and `--` (decrement) operators are available,
both in prefix and postfix notation:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=plusplus_minusminus,indent=0]
----
<1> The postfix increment will increment `a` after the expression has been evaluated and assigned into `b`
<2> The postfix decrement will decrement `c` after the expression has been evaluated and assigned into `d`
<3> The prefix increment will increment `e` before the expression is evaluated and assigned into `f`
<4> The prefix decrement will decrement `g` before the expression is evaluated and assigned into `h`

=== Assignment arithmetic operators

The binary arithmetic operators we have seen above are also available in an assignment form:

* `+=`
* `-=`
* `*=`
* `/=`
* `%=`
* `**=`

Let's see them in action:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=binary_assign_operators,indent=0]
----

== Relational operators

Relational operators allow comparisons between objects, to know if two objects are the same or different,
or if one is greater than, less than, or equal to the other.

The following operators are available:

[cols="1,1" options="header"]
|====
| Operator
| Purpose

| `==`
| equal

| `!=`
| different

| `<`
| less than

| `\<=`
| less than or equal

| `>`
| greater than

| `>=`
| greater than or equal
|====

Here are some examples of simple number comparisons using these operators:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=simple_relational_op,indent=0]
----

== Logical operators

Groovy offers three logical operators for boolean expressions:

* `&&`: logical "and"
* `||`: logical "or"
* `!`: logical "not"

Let's illustrate them with the following examples:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=logical_op,indent=0]
----
<1> "not" false is true
<2> true "and" true is true
<3> true "or" false is true

=== Precedence

The logical "not" has a higher priority than the logical "and".

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=logical_precendence_1,indent=0]
----
<1> Here, the assertion is true (as the expression in parentheses is false), because "not" has a higher precedence than "and", so it only applies to the first "false" term; otherwise, it would have applied to the result of the "and", turned it into true, and the assertion would have failed

The logical "and" has a higher priority than the logical "or".

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=logical_precendence_2,indent=0]
----
<1> Here, the assertion is true, because "and" has a higher precedence than "or", therefore the "or" is executed last and returns true, having one true argument; otherwise, the "and" would have executed last and returned false, having one false argument, and the assertion would have failed

=== Short-circuiting

The logical `||` operator supports short-circuiting: if the left operand is true, it knows that the result will be true in any case, so it won't evaluate the right operand.
The right operand will be evaluated only if the left operand is false.

Likewise for the logical `&&` operator: if the left operand is false, it knows that the result will be false in any case, so it won't evaluate the right operand.
The right operand will be evaluated only if the left operand is true.

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=logical_shortcircuit,indent=0]
----
<1> We create a function that sets the `called` flag to true whenever it's called
<2> In the first case, after resetting the called flag, we confirm that if the left operand to `||` is true, the function is not called, as `||` short-circuits the evaluation of the right operand
<3> In the second case, the left operand is false and so the function is called, as indicated by the fact our flag is now true
<4> Likewise for `&&`, we confirm that the function is not called with a false left operand
<5> But the function is called with a true left operand

== Bitwise operators

Groovy offers 4 bitwise operators:

* `&`: bitwise "and"
* `|`: bitwise "or"
* `^`: bitwise "xor" (exclusive "or")
* `~`: bitwise negation

Bitwise operators can be applied on a `byte` or an `int` and return an `int`:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=bitwise_op,indent=0]
----
<1> bitwise and
<2> bitwise and returns common bits
<3> bitwise or
<4> bitwise or returns all '1' bits
<5> setting a mask to check only the last 8 bits
<6> bitwise exclusive or on self returns 0
<7> bitwise exclusive or
<8> bitwise negation

It's worth noting that the internal representation of primitive types follow the http://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html[Java Language Specification]. In particular,
primitive types are signed, meaning that for a bitwise negation, it is always good to use a mask to retrieve only the necessary bits.

In Groovy, bitwise operators have the particularity of being <<Operator-Overloading,overloadable>>, meaning that you can define the behavior of those operators for any kind of object.

== Conditional operators

=== Not operator

The "not" operator is represented with an exclamation mark (`!`) and inverts the result of the underlying boolean expression. In
particular, it is possible to combine the `not` operator with the <<core-semantics.adoc#Groovy-Truth,Groovy truth>>:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=conditional_op_not,indent=0]
----
<1> the negation of `true` is `false`
<2> 'foo' is a non empty string, evaluating to `true`, so negation returns `false`
<3> '' is an empty string, evaluating to `false`, so negation returns `true`

=== Ternary operator

The ternary operator is a shortcut expression that is equivalent to an if/else branch assigning some value to a variable.

Instead of:
[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=conditional_op_ternary_if,indent=0]
----

You can write:
[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=conditional_op_ternary_ternary,indent=0]
----

The ternary operator is also compatible with the <<core-semantics.adoc#Groovy-Truth,Groovy truth>>, so you can make it even simpler:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=conditional_op_ternary_groovytruth,indent=0]
----

=== Elvis operator

The "Elvis operator" is a shortening of the ternary operator. One instance of where this is handy is for returning
a 'sensible default' value if an expression resolves to `false`-ish (as in
<<core-semantics.adoc#Groovy-Truth,Groovy truth>>). A simple example might look like this:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=conditional_op_elvis,indent=0]
----
<1> with the ternary operator, you have to repeat the value you want to assign
<2> with the Elvis operator, the value, which is tested, is used if it is not `false`-ish

Usage of the Elvis operator reduces the verbosity of your code and reduces the risks of errors in case of refactorings,
by removing the need to duplicate the expression which is tested in both the condition and the positive return value.

== Object operators

=== Safe navigation operator

The Safe Navigation operator is used to avoid a `NullPointerException`. Typically when you have a reference to an object
you might need to verify that it is not `null` before accessing methods or properties of the object. To avoid this, the safe
navigation operator will simply return `null` instead of throwing an exception, like so:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=nullsafe,indent=0]
----
<1> `find` will return a `null` instance
<2> use of the null-safe operator prevents from a `NullPointerException`
<3> result is `null`

=== Direct field access operator

Normally in Groovy, when you write code like this:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=direct_field_class,indent=0]
----
<1> public field `name`
<2> a getter for `name` that returns a custom string
<3> calls the getter

The `user.name` call triggers a call to the property of the same name, that is to say, here, to the getter for `name`. If
you want to retrieve the field instead of calling the getter, you can use the direct field access operator:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=direct_field_op,indent=0]
----
<1> use of `.@` forces usage of the field instead of the getter

[[method-pointer-operator]]
=== Method pointer operator

The method pointer operator (`.&`) call be used to store a reference to a method in a variable, in order to call it
later:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=method_reference,indent=0]
----
<1> the `str` variable contains a `String`
<2> we store a reference to the `toUpperCase` method on the `str` instance inside a variable named `fun`
<3> `fun` can be called like a regular method
<4> we can check that the result is the same as if we had called it directly on `str`

There are multiple advantages in using method pointers. First of all, the type of such a method pointer is
a `groovy.lang.Closure`, so it can be used in any place a closure would be used. In particular, it is suitable to
convert an existing method for the needs of the strategy pattern:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=method_reference_strategy,indent=0]
----
<1> the `transform` method takes each element of the list and calls the `action` closure on them, returning a new list
<2> we define a function that takes a `Person` and returns a `String`
<3> we create a method pointer on that function
<4> we create the list of elements we want to collect the descriptors
<5> the method pointer can be used where a `Closure` was expected

Method pointers are bound by the receiver and a method name. Arguments are resolved at runtime, meaning that if you have
multiple methods with the same name, the syntax is not different, only resolution of the appropriate method to be called
will be done at runtime:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=method_reference_dispatch,indent=0]
----
<1> define an overloaded `doSomething` method accepting a `String` as an argument
<2> define an overloaded `doSomething` method accepting an `Integer` as an argument
<3> create a single method pointer on `doSomething`, without specifying argument types
<4> using the method pointer with a `String` calls the `String` version of `doSomething`
<5> using the method pointer with an `Integer` calls the `Integer` version of `doSomething`

== Regular expression operators

=== Pattern operator

The pattern operator (`~`) provides a simple way to create a `java.util.regex.Pattern` instance:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=pattern_op,indent=0]
----

while in general, you find the pattern operator with an expression in a slashy-string, it can be used with any kind of
`String` in Groovy:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=pattern_op_variants,indent=0]
----
<1> using single quote strings
<2> using double quotes strings
<3> the dollar-slashy string lets you use slashes and the dollar sign without having to escape them
<4> you can also use a GString!

=== Find operator

Alternatively to building a pattern, you can directly use the find operator `=~` to build a `java.util.regex.Matcher`
instance:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=pattern_matcher_op,indent=0]
----
<1> `=~` creates a matcher against the `text` variable, using the pattern on the right hand side
<2> the return type of `=~` is a `Matcher`
<3> equivalent to calling `if (!m.find())`

Since a `Matcher` coerces to a `boolean` by calling its `find` method, the `=~` operator is consistent with the simple
use of Perl's `=~` operator, when it appears as a predicate (in `if`, `while`, etc.).

=== Match operator

The match operator (`==~`) is a slight variation of the find operator, that does not return a `Matcher` but a boolean
and requires a strict match of the input string:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=pattern_matcher_strict_op,indent=0]
----
<1> `==~` matches the subject with the regular expression, but match must be strict
<2> the return type of `==~` is therefore a `boolean`
<3> equivalent to calling `if (text ==~ /match/)`

== Other operators

=== Spread operator

The Spread Operator (`*.`) is used to invoke an action on all items of an aggregate object. It is equivalent to calling the action on each item
and collecting the result into a list:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=spreaddot,indent=0]
----
<1> build a list of `Car` items. The list is an aggregate of objects.
<2> call the spread operator on the list, accessing the `make` property of each item
<3> returns a list of strings corresponding to the collection of `make` items

The spread operator is null-safe, meaning that if an element of the collection is null, it will return null instead of throwing a `NullPointerException`:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=spreaddot_nullsafe,indent=0]
----
<1> build a list for which of of the elements is `null`
<2> using the spread operator will *not* throw a `NullPointerException`
<3> the receiver might also be null, in which case the return value is `null`

The spread operator can be used on any class which implements the `Iterable` interface:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=spreaddot_iterable,indent=0]
----

==== Spreading method arguments

There may be situations when the arguments of a method call can be found in a list that you need to adapt to the method
arguments. In such situations, you can use the spread operator to call the method. For example, imagine you have the
following method signature:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=spreadmethodargs_method,indent=0]
----

then if you have the following list:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=spreadmethodargs_args,indent=0]
----

you can call the method without having to define intermediate variables:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=spreadmethodargs_assert,indent=0]
----

It is even possible to mix normal arguments with spread ones:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=spreadmethodargs_mixed,indent=0]
----

==== Spread list elements

When used inside a list literal, the spread operator acts as if the spread element contents were inlined into the list:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=spread_list,indent=0]
----
<1> `items` is a list
<2> we want to insert the contents of the `items` list directly into `list` without having to call `addAll`
<3> the contents of `items` has been inlined into `list`

==== Spread map elements

The spread map operator works in a similar manner as the spread list operator, but for maps. It allows you to inline
the contents of a map into another map literal, like in the following example:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=spread_map,indent=0]
----
<1> `m1` is the map that we want to inline
<2> we use the `*:m1` notation to spread the contents of `m1` into `map`
<3> `map` contains all the elements of `m1`

The position of the spread map operator is relevant, like illustrated in the following example:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=spread_map_position,indent=0]
----
<1> `m1` is the map that we want to inline
<2> we use the `*:m1` notation to spread the contents of `m1` into `map`, but redefine the key `d` **after** spreading
<3> `map` contains all the expected keys, but `d` was redefined

=== Range operator

Groovy supports the concept of ranges and provides a notation (`..`) to create ranges of objects:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=intrange,indent=0]
----
<1> a simple range of integers, stored into a local variable
<2> an `IntRange`, with inclusive bounds
<3> an `IntRange`, with exclusive upper bound
<4> a `groovy.lang.Range` implements the `List` interface
<5> meaning that you can call the `size` method on it

Ranges implementation is lightweight, meaning that only the lower and upper bounds are stored. You can create a range
from any `Comparable` object that has `next()` and `previous()` methods to determine the next / previous item in the range.
For example, you can create a range of characters this way:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=charrange,indent=0]
----

=== Spaceship operator

The spaceship operator (`pass:[<=>]`) delegates to the `compareTo` method:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=spaceship,indent=0]
----

[[subscript-operator]]
=== Subscript operator

The subscript operator is a short hand notation for `getAt` or `putAt`, depending on whether you find it on
the left hand side or the right hand side of an assignment:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=subscript_op,indent=0]
----
<1> `[2]` can be used instead of `getAt(2)`
<2> if on left hand side of an assignment, will call `putAt`
<3> `getAt` also supports ranges
<4> so does `putAt`
<5> the list is mutated

[[custom-subscript-operator]]
The subscript operator, in combination with a custom implementation of `getAt`/`putAt` is a convenient way for destructuring
objects:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=subscript_destructuring,indent=0]
----
<1> the `User` class defines a custom `getAt` implementation
<2> the `User` class defines a custom `putAt` implementation
<3> create a sample user
<4> using the subscript operator with index 0 allows retrieving the user id
<5> using the subscript operator with index 1 allows retrieving the user name
<6> we can use the subscript operator to write to a property thanks to the delegation to `putAt`
<7> and check that it's really the property `name` which was changed

=== Membership operator

The membership operator (`in`) is equivalent to calling the `isCase` method. In the context of a `List`, it is equivalent
to calling `contains`, like in the following example:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=membership_op,indent=0]
----
<1> equivalent to calling `list.contains('Emmy')` or `list.isCase('Emmy')`

=== Identity operator

In Groovy, using `==` to test equality is different from using the same operator in Java. In Groovy, it is calling `equals`.
If you want to compare reference equality, you should use `is` like in the following example:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=identity_op,indent=0]
----
<1> Create a list of strings
<2> Create another list of strings containing the same elements
<3> using `==`, we test object equality
<4> but using `is`, we can check that references are distinct

=== Coercion operator

The coercion operator (`as`) is a variant of casting. Coercion converts object from one type to another *without* them
being compatible for assignment. Let's take an example:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=coerce_op_cast,indent=0]
----
<1> `Integer` is not assignable to a `String`, so it will produce a `ClassCastException` at runtime

This can be fixed by using _coercion_ instead:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=coerce_op,indent=0]
----
<1> `Integer` is not assignable to a `String`, but use of `as` will _coerce_ it to a `String`

When an object is coerced into another, unless the target type is the same as the source type, coercion will return a
*new* object. The rules of coercion differ depending on the source and target types, and coercion may fail if no conversion
rules are found. Custom conversion rules may be implemented thanks to the `asType` method:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=coerce_op_custom,indent=0]
----
<1> the `User` class defines a custom conversion rule from `User` to `Identifiable`
<2> we create an instance of `User`
<3> we coerce the `User` instance into an `Identifiable`
<4> the target is an instance of `Identifiable`
<5> the target is not an instance of `User` anymore

=== Diamond operator

The diamond operator (`<>`) is a syntactic sugar only operator added to support compatibility with the operator of the
same name in Java 7. It is used to indicate that generic types should be inferred from the declaration:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=diamond_op,indent=0]
----

In dynamic Groovy, this is totally unused. In statically type checked Groovy, it is also optional since the Groovy
type checker performs type inference whether this operator is present or not.

=== Call operator

The call operator `()` is used to call a method named `call` implicitly. For any object which defines a `call` method,
 you can omit the `.call` part and use the call operator instead:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=call_op,indent=0]
----
<1> `MyCallable` defines a method named `call`. Note that it doesn't need to implement `java.util.concurrent.Callable`
<2> we can call the method using the classic method call syntax
<3> or we can omit `.call` thanks to the call operator

== Operator precedence
The table below lists all groovy operators in order of precedence.

[options="header"]
|======================
|Level | Operator(s) | Name(s)
| 1 | `new` &#160; `()` | object creation, explicit parentheses
|   | `()` &#160; `{}` &#160; `[]` | method call, closure, literal list/map
|   | `.` &#160; `.&` &#160; `.@` | member access, method closure, field/attribute access
|   | `?.` &#160; `\*` &#160; `*.` &#160; `*:` | safe dereferencing, spread, spread-dot, spread-map
|   | `~` &#160; `!` &#160; `(type)` | bitwise negate/pattern, not, typecast
|   | `[]` &#160; `++` &#160; `--` | list/map/array index, post inc/decrement
| 2 | `**` | power
| 3 | `++` &#160; `--` &#160; `+` &#160; `-` | pre inc/decrement, unary plus, unary minus
| 4 | `*` &#160; `/` &#160; `%` | multiply, div, remainder
| 5 | `+` &#160; `-` | addition, subtraction
| 6 | `<<` &#160; `>>` &#160; `>>>` &#160; `..` &#160; `..<` | left/right (unsigned) shift, inclusive/exclusive range
| 7 | `<` &#160; `\<=` &#160; `>` &#160; `>=` &#160; `in` &#160; `instanceof` &#160; `as` | less/greater than/or equal, in, instanceof, type coercion
| 8 | `==` &#160; `!=` &#160; `pass:[<=>]` | equals, not equals, compare to
|   | `=~` &#160; `==~` | regex find, regex match
| 9 | `&` | binary/bitwise and
| 10 | `^` | binary/bitwise xor
| 11 | `\|` | binary/bitwise or
| 12 | `&&` | logical and
| 13 | `\|\|` | logical or
| 14 | `? :` | ternary conditional
|    | `?:` | elvis operator
| 15 | `=` &#160; `\**=` &#160; `*=` &#160; `/=` &#160; `%=` &#160; `+=` &#160; `-=` &#160; +
`pass:[<<=]` &#160; `>>=` &#160; `>>>=` &#160; `&=` &#160; `^=` &#160; `\|=` | various assignments
|======================

[[Operator-Overloading]]
== Operator overloading

Groovy allows you to overload the various operators so that they can be used with your own classes. Consider this simple
class:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=operator_overload_class,indent=0]
----
<1> `Bucket` implements a special method called `plus()`

Just by implementing the `plus()` method, the `Bucket` class can now be used with the `+` operator like so:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=operator_overload_op,indent=0]
----
<1> The two `Bucket` objects can be added together with the `+` operator

All (non-comparator) Groovy operators have a corresponding method that you can implement in your own classes. The only
requirements are that your method is public, has the correct name, and has the correct number of arguments. The argument
types depend on what types you want to support on the right hand side of the operator. For example, you could support
the statement

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=operator_overload_mixed_op,indent=0]
----

by implementing the `plus()` method with this signature:

[source,groovy]
----
include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=operator_overload_mixed_class,indent=0]
----

Here is a complete list of the operators and their corresponding methods:

[cols="1,1,1,1" options="header"]
|====
| Operator
| Method
| Operator
| Method

| `+`
| a.plus(b)
| `a[b]`
| a.getAt(b)

| `-`
| a.minus(b)
| `a[b] = c`
| a.putAt(b, c)

| `*`
| a.multiply(b)
| `a in b`
| b.isCase(a)

| `/`
| a.div(b)
| `<<`
| a.leftShift(b)

| `%`
| a.mod(b)
| `>>`
| a.rightShift(b)

| `**`
| a.power(b)
| `>>>`
| a.rightShiftUnsigned(b)

| `\|`
| a.or(b)
| `++`
| a.next()

| `&`
| a.and(b)
| `--`
| a.previous()

| `^`
| a.xor(b)
| `+a`
| a.positive()

| `as`
| a.asType(b)
| `-a`
| a.negative()

| `a()`
| a.call()
| `~a`
| a.bitwiseNegate()
|====

