Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Ruby

Thành thạo Method Delegation trong Ruby & Rails: Hướng dẫn thực tế

Bài viết về method delegation trong Ruby.

Bạn sẽ học dùng phương thức delegate, module Forwardable và class SimpleDelegator.

Tại sao cần delegation?

Trong OOP, có hai cách class làm việc cùng nhau.

Chúng là:

  • Inheritance (Kế thừa)
  • Composition (Hợp thành)

Với inheritance, bạn tạo class hierarchy, class cha share phương thức, constant và định nghĩa instance variable với class con kế thừa.

Ví dụ:

Trong Ruby, mọi object kế thừa từ class Object mặc định.

Đó là lý do bạn có phương thức puts, class, object_id.

Với composition, class tạo (hoặc được cho) object từ class khác… rồi dùng object này delegate công việc cho chúng.

Ví dụ:

Máy tính gồm nhiều phần (object) và mỗi phần biết làm tốt một việc.

Nếu muốn render màn hình, máy tính bảo card đồ họa hiển thị gì, nhưng không bảo CÁCH LÀM.

Đó là composition!

Nhưng nếu bạn là máy tính và muốn cho truy cập phương thức card đồ họa?

Bạn phải xây "cầu nối" giữa chúng.

Hãy xem cách làm.

Ví dụ Method Delegation Ruby

Chúng ta có hai class:

  • Computer
  • Memory

Cho code sau:

 class Computer
  def initialize
    @memory = Memory.new
  end
end
class Memory
  def initialize
    @data = []
  end
  def write(data)
    @data << data
  end
  def read(index)
    @data[index]
  end
end
computer = Computer.new 

Chúng ta muốn truy cập memory chỉ qua Computer.

Có nhiều lý do:

  • Chỉ có 1 unit memory, nghĩa là chỉ muốn 1 memory object. Tập trung truy cập trong 1 object đạt được điều đó.
  • Muốn kiểm soát ai truy cập memory (ứng dụng khác nhau) và dùng phần memory nào.
  • Muốn log mọi truy cập memory cho bảo mật hoặc debug.

Bây giờ, nếu thử:

 computer.write("rubyguides") 

Sẽ fail với NoMethodError vì không có write trên Computer.

 undefined method `write' for # (NoMethodError) 

Class Computer không hiểu bạn nói write là gì.

Trừ khi…

Bạn tạo phương thức write!

Cách làm:

 class Computer
  def initialize
    @memory = Memory.new
  end
  def write(data)
    @memory.write(data)
  end
  def read(index)
    @memory.read(index)
  end
end 

Chúng ta chuyển request sang object @memory.

Đó là method delegation.

Lưu ý: Điều này làm các phương thức thành public interface (có sẵn cho mọi người) và bạn không lúc nào cũng muốn vậy.

Có shortcut cho method delegation không?

Có!

Hãy xem…

Cách dùng Module Forwardable

Bây giờ:

Bạn dùng module Forwardable built-in Ruby để định nghĩa delegator method.

Hoạt động như sau:

 require 'forwardable'
class Computer
  extend Forwardable
  def_delegators :@memory, :read, :write
  def initialize
    @memory = Memory.new
  end
end 

Này cho phép xóa phương thức chúng ta tạo trước và làm giống hệt.

Forwardable lo argument phương thức (kể cả block!) cho bạn, không lo về đó.

Thú vị không? 🙂

Cách dùng Rails Delegate Method

Nếu dùng Rails, hoặc gem ActiveSupport riêng, bạn có phương thức delegate.

Cách hoạt động:

 class Computer
  delegate :read, :write, to: :@memory
  def initialize
    @memory = Memory.new
  end
end 

Phương thức delegate nhận đối số prefix, cho phép thêm prefix vào tên phương thức.

Ví dụ:

 class Computer
  delegate :read, :write, prefix: "memory", to: :@memory
  def initialize
    @memory = Memory.new
  end
end 

Kết quả hai phương thức:

  • memory_read
  • memory_write

Cách Delegate Everything với SimpleDelegator

Kỹ thuật bạn học dùng forward/delegate phương thức cụ thể.

Nhưng nếu muốn wrap object và expose TẤT CẢ phương thức…

Bạn dùng class SimpleDelegator!

Cách làm:

 require 'delegate'
class CoolArray < SimpleDelegator
end
cool = CoolArray.new([])
cool << "ruby"
cool << "gems"
p cool 

Giờ CoolArray behave như object truyền vào new.

Tại sao hữu ích?

Bạn thêm phương thức mới vào object này, không phải thay đổi class gốc.

Video hướng dẫn

Tóm tắt

Bạn đã học về object composition trong Ruby và cách delegate phương thức dùng các kỹ thuật khác nhau!

Nếu thích bài viết hãy chia sẻ với bạn bè Ruby.

Cảm ơn đã đọc 🙂