List of Ruby Operators That Can Be Overridden/Implemented

list of ruby operators that can be overridden/implemented

Here's a table of the Ruby operators.

The ones that are methods and overloadable are:

[ ] [ ]=    Element reference, element set
** Exponentiation
! ~ + - Not, complement, unary plus and minus (method names for the last two are +@ and -@)
* / % Multiply, divide, and modulo
+ - Plus and minus
>> << Right and left shift
& Bitwise `and'
^ | Bitwise exclusive `or' and regular `or'
<= < > >= Comparison operators
<=> == === != =~ !~ Equality and pattern match operators (!= and !~ may not be defined as methods)

The table was from the 2001 Pickaxe book, but that's the same table as in the Ruby 1.9 Pickaxe book -- no reason to believe that this set of infix operators will ever change.

Ruby method for +=

The += operator is not associated to any method, it is just syntactic sugar, when you write a += b the Ruby interpreter transform it to a = a + b, the same is for a.b += c that is transformed to a.b = a.b + c. Thus you just have to define the methods x= and x as you need:

class Plane 
def initialize
@moved = 0
@x = 0
end

attr_reader :x
def x=(x)
@x = x
@moved += 1
end

def to_s
"moved #{@moved} times, current x is #{@x}"
end

end

plane = Plane.new
plane.x += 5
plane.x += 10
puts plane.to_s
# => moved 2 times, current x is 15

question on overriding + operator in ruby

You should not mutate the object when implementing + operator. Instead return a new Point Object:

class Point
attr_accessor :x, :y

def initialize(x,y)
@x, @y = x, y
end


def +(other)
Point.new(@x + other.x, @y + other.y)
end


def to_s
"(#{@x}, #{@y})"
end
end

ruby-1.8.7-p302:
> p1 = Point.new(1,2)
=> #<Point:0x10031f870 @y=2, @x=1>
> p2 = Point.new(3, 4)
=> #<Point:0x1001bb718 @y=4, @x=3>
> p1 + p2
=> #<Point:0x1001a44c8 @y=6, @x=4>
> p3 = p1 + p2
=> #<Point:0x1001911e8 @y=6, @x=4>
> p3
=> #<Point:0x1001911e8 @y=6, @x=4>
> p1 += p2
=> #<Point:0x1001877b0 @y=6, @x=4>
> p1
=> #<Point:0x1001877b0 @y=6, @x=4>

Overriding instance variable array's operators in Ruby

I think you're looking for this:

class Test
def initialize
@myarray = []
class << @myarray
def <<(val)
puts "adding #{val}" # or whatever it is you want to do first
super(val)
end
end
end
attr_accessor :myarray
end

There's a good article about this and related topics at Understanding Ruby Singleton Classes.

Can I implement += in my class to increase a contained value?

Since c += 100 is just a sugar for c = c + 100, you can't escape overwriting c. BUT you can overwrite it with a similar object (and not with fixnum, as in your question).

class Container
def initialize(value = 0)
@value = value
end

def + (other)
Container.new(@value + other)
end

def get
@value
end
end

c = Container.new(100)
c += 100
c.get # => 200

Can Ruby define some generic operator?

There is a fixed set of operators in Ruby, some of which are syntactic sugar for message sends and can thus be overridden.

You can't add new operators. In Ruby, the fixed set of operators is part of the language syntax, and Ruby doesn't allow Ruby code to change the syntax of the language. If you want to add a new operator, you will have to convince matz to change the language specification, and you will have to convince the developers of Rubinius, JRuby, YARV, MagLev, and MRuby to implement this change.

Overridable

These desugar into message sends and thus can be overridden by implementing the corresponding methods.

  • unary prefix

    • +foofoo.+@(), ergo: def +@; end
    • -foofoo.-@(), ergo: def -@; end
    • !foofoo.!(), ergo: def !; end
    • ~foofoo.~(), ergo: def ~; end
  • binary infix

    • foo + barfoo.+(bar), ergo: def +(other) end
    • foo - barfoo.-(bar), ergo: def -(other) end
    • foo * barfoo.*(bar), ergo: def *(other) end
    • foo / barfoo./(bar), ergo: def /(other) end
    • foo % barfoo.%(bar), ergo: def %(other) end
    • foo ** barfoo.**(bar), ergo: def **(other) end
    • foo >> barfoo.>>(bar), ergo: def >>(other) end
    • foo << barfoo.<<(bar), ergo: def <<(other) end
    • foo & barfoo.&(bar), ergo: def &(other) end
    • foo ^ barfoo.^(bar), ergo: def ^(other) end
    • foo | barfoo.|(bar), ergo: def |(other) end
    • foo < barfoo.<(bar), ergo: def <(other) end
    • foo > barfoo.>(bar), ergo: def >(other) end
    • foo <= barfoo.<=(bar), ergo: def <=(other) end
    • foo >= barfoo.>=(bar), ergo: def >=(other) end
    • foo == barfoo.==(bar), ergo: def ==(other) end
    • foo === barfoo.===(bar), ergo: def ===(other) end
    • foo != barfoo.!=(bar), ergo: def !=(other) end
    • foo =~ barfoo.=~(bar), ergo: def =~(other) end
    • foo !~ barfoo.!~(bar), ergo: def !~(other) end
    • foo <=> barfoo.<=>(bar), ergo: def <=>(other) end
  • n-ary "around-fix"

    • foo[bar, baz]foo.[](bar, baz), ergo: def [](a, b) end
    • foo[bar, baz] = quuxfoo.[]=(bar, baz, quux), ergo: def []=(a, b, c) end
    • foo.(bar, baz)foo.call(bar, baz), ergo: def call(a, b) end

Non-overridable

These don't desugar into message sends.

  • unary prefix

    • defined?
  • binary infix

    • foo && bar
    • foo and bar
    • foo || bar
    • foo or bar
    • foo = bar
  • compound assignment

    • foo ||= bar
    • foo &&= bar

Sort-of overridable

You can't override these independently, but they (at least partially) translate into other operators that can be overridden.

  • unary prefix

    • not foofoo.!(), ergo: def !; end
  • compound assignment

    • foo ω= barfoo = foo ω bar for any ω ∉ { ||, && }

are Ruby's logical operators methods, like binary operators are?

These are the operators that cannot be (re)defined:

  • &&, || (AND, OR)
  • .., ... (range)
  • ?: (ternary)
  • rescue
  • = (and **=, &&=, &=, *=, +=. -=, <<=, >>= , ||=, |=, ^=)
  • defined?
  • not
  • and, or
  • if, unless, while, until

The others, like (incomplete list) !, ~, +, -, **, *, /, %, >>, ==, != are implemented as methods and can be redefined.

Override for an array instance variable in class

class Player
attr_accessor :moves

def initialize
@moves = []
@moves.define_singleton_method(:<<) do |value|
raise Exception if include?(value)
push(value)
end
end
end

You can add methods only specific to a given object using the Object#define_singleton_method. Ruby is really flexible when it comes to meta programming.

However such tools should be used sparingly. I don't know your specific situation, but you are probably better off not giving direct access to @moves. The best approach might be to define methods in Player that create an indirect and more restrictive interface to the internal representation and give you more control.



Related Topics



Leave a reply



Submit