Menu
Coddy logo textTech

Metodi degli operatori

Fa parte della sezione Programmazione orientata agli oggetti del percorso Ruby di Coddy. Lezione 38 di 57.

La maggior parte degli operatori di Ruby sono metodi. a + b chiama a.+(b), quindi una classe definisce + come qualsiasi altro metodo. Le operazioni aritmetiche sugli oggetti valore restituiscono un oggetto nuovo e lasciano invariati entrambi gli operandi:

class Vector
  attr_reader :x, :y

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

  def +(other)
    Vector.new(x + other.x, y + other.y)
  end

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

a = Vector.new(1, 2)
b = Vector.new(3, 4)
puts a + b
puts a

Output:

(4, 6)
(1, 2)

L’operando destro può essere un altro tipo di valore, ad esempio un numero per il ridimensionamento. Il meno unario è il metodo -@:

class Vector
  attr_reader :x, :y

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

  def -(other)
    Vector.new(x - other.x, y - other.y)
  end

  def *(factor)
    Vector.new(x * factor, y * factor)
  end

  def -@
    Vector.new(-x, -y)
  end

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

v = Vector.new(3, 4)
puts v * 2
puts v - Vector.new(1, 1)
puts(-v)

Output:

(6, 8)
(2, 3)
(-3, -4)

Una volta che + esiste, funziona anche +=, perché a += b significa a = a + b. sum funziona anche quando gli viene fornito un valore iniziale della tua classe:

class Money
  attr_reader :cents

  def initialize(cents)
    @cents = cents
  end

  def +(other)
    Money.new(cents + other.cents)
  end

  def to_s
    format("$%.2f", cents / 100.0)
  end
end

total = Money.new(0)
total += Money.new(250)
total += Money.new(199)
puts total
puts [Money.new(100), Money.new(5)].sum(Money.new(0))

Output:

$4.49
$1.05

Anche <=> è un operatore. Insieme a Comparable, consente di confrontare e ordinare gli oggetti Money, e un operatore può rifiutare un operando non compatibile generando un'eccezione, come fanno i numeri:

class Money
  include Comparable
  attr_reader :cents, :currency

  def initialize(cents, currency)
    @cents = cents
    @currency = currency
  end

  def +(other)
    raise ArgumentError, "cannot add #{other.currency} to #{currency}" unless other.currency == currency

    Money.new(cents + other.cents, currency)
  end

  def <=>(other)
    cents <=> other.cents
  end
end

puts Money.new(500, "EUR") > Money.new(300, "EUR")
begin
  Money.new(1, "EUR") + Money.new(1, "USD")
rescue ArgumentError => e
  puts e.message
end

Output:

true
cannot add USD to EUR
challenge icon

Sfida

Facile

Completa la classe Vector. Definisci + e - per due vettori, * per un vettore e un numero, il meno unario -@, == per confrontare entrambe le coordinate e to_s, che restituisce (4, 6). length restituisce la lunghezza del vettore usando Math.sqrt.

Il codice fornito legge espressioni: 1,2 + 3,4, 1,2 - 3,4, 1,2 * 3, neg 1,2 e 1,2 == 1,2. Stampa ogni risultato e, per i risultati vettoriali, anche length 7.21 con due cifre decimali.

Il tuo codice va inserito in vector.rb. main.rb contiene il codice fornito per l'input/output e non può essere modificato.

Provalo tu

require_relative 'vector'

# Supplied input/output code: keep it as it is
input = []
while (line = gets)
  input << line.chomp
end
def vec(text)
  Vector.new(*text.split(",").map(&:to_i))
end

input.each do |line|
  parts = line.split
  result = if parts[0] == "neg" then -vec(parts[1])
           else
             a = vec(parts[0])
             case parts[1]
             when "+" then a + vec(parts[2])
             when "-" then a - vec(parts[2])
             when "*" then a * parts[2].to_i
             else a == vec(parts[2])
             end
           end
  puts result
  puts format("length %.2f", result.length) if result.is_a?(Vector)
end
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore Ruby online