Menu
CoddyTech

Phương thức toán tử

Thuộc phần Lập trình hướng đối tượng trong hành trình Ruby của Coddy. Bài học 38 trên 57.

Hầu hết toán tử trong Ruby đều là phương thức. a + b gọi a.+(b), vì vậy một lớp định nghĩa + như mọi phương thức khác. Phép tính số học trên các đối tượng giá trị trả về một đối tượng mới và giữ nguyên cả hai toán hạng:

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

Đầu ra:

(4, 6)
(1, 2)

Toán hạng bên phải có thể là một kiểu giá trị khác, chẳng hạn như một số dùng để nhân tỷ lệ. Phép trừ một ngôi là phương thức -@:

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)

Đầu ra:

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

Khi đã có +, += cũng hoạt động, vì a += b có nghĩa là a = a + b. sum cũng hoạt động khi bạn cung cấp giá trị khởi đầu thuộc lớp của mình:

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))

Đầu ra:

$4.49
$1.05

<=> cũng là một toán tử. Kết hợp với Comparable, nó cho phép so sánh và sắp xếp các đối tượng Money, còn toán tử có thể từ chối một toán hạng không khớp bằng cách phát sinh lỗi, giống như với các số:

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

Đầu ra:

true
cannot add USD to EUR
challenge icon

Thử thách

Dễ

Hoàn thiện lớp Vector. Định nghĩa các toán tử + và - cho hai vector, * cho một vector và một số, dấu trừ một ngôi -@, == để so sánh cả hai tọa độ, và to_s, hàm này trả về (4, 6). length trả về độ dài của vector bằng Math.sqrt.

Code được cung cấp đọc các biểu thức: 1,2 + 3,4, 1,2 - 3,4, 1,2 * 3, neg 1,2 và 1,2 == 1,2. Code in ra kết quả của từng biểu thức, và với kết quả là vector, còn in ra length 7.21 với hai chữ số thập phân.

Phần code của bạn nằm trong vector.rb. main.rb chứa code đầu vào/đầu ra được cung cấp và bạn không thể chỉnh sửa tệp này.

Tự làm thử

require_relative 'vector'

# Đoạn code đầu vào/đầu ra có sẵn: giữ nguyên
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 iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Lập trình hướng đối tượng

Tự luyện tập: Trình biên dịch Ruby online