Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Ruby

เชี่ยวชาญ Method Delegation ใน Ruby & Rails: คู่มือปฏิบัติ

บทความนี้เกี่ยวกับ method delegation ใน Ruby

คุณจะเรียนรู้วิธีใช้เมธอด delegate, โมดูล Forwardable และคลาส SimpleDelegator

ทำไมเราต้องการ delegation?

ใน Object-Oriented Programming มีสองวิธีสำหรับคลาสทำงานร่วมกัน

คือ:

  • Inheritance (การสืบทอด)
  • Composition (การประกอบ)

ด้วย inheritance คุณสร้าง class hierarchies ที่ parent class แชร์เมธอด constants และ instance variable definitions ให้คลาสที่สืบทอด

ตัวอย่าง:

ใน Ruby ทุกออบเจกต์สืบทอดจากคลาส Object โดย default

นั่นคือเหตุผลที่คุณเข้าถึงเมธอดอย่าง puts, class และ object_id ได้

ด้วย composition คลาสสร้าง (หรือได้รับ) ออบเจกต์จากอีกคลาส… แล้วใช้ออบเจกต์เหล่านี้ delegate งานให้พวกมัน

ตัวอย่าง:

คอมพิวเตอร์ประกอบด้วยหลายส่วน (ออบเจกต์) และแต่ละส่วนรู้จักทำอย่างเดียวดี

หากอยาก render บนหน้าจอ คอมพิวเตอร์จะบอก graphics card ให้แสดงอะไร แต่ไม่บอกวิธีทำ

นั่นคือ composition!

แตถ้าคุณคือคอมพิวเตอร์ และอยากให้เข้าถึงเมธอดของ graphics card?

คุณต้องสร้าง "bridge" ระหว่างพวกมัน

มา看看วิธีทำ

Ruby Method Delegation — ตัวอย่าง

เรามีสองคลาส:

  • Computer
  • Memory

โค้ดที่กำหนด:

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

เราอยากเข้าถึง memory ผ่าน Computer เท่านั้น

อาจมีหลายเหตุผล:

  • คุณมี memory unit เดียว หมายถึงอยากมี memory object เดียว โดย centralize access ในออบเจกต์เดียว คุณบรรลุได้
  • อยากควบคุมว่าใครเข้าถึง memory (แอปพลิเคชันต่างๆ) และส่วนไหนของ memory ที่เข้าถึงได้
  • อยาก log ทุก memory access เพื่อ security หรือ debugging

ตอนนี้ หากลองทำนี้:

computer.write("rubyguides")

จะ fail ด้วย NoMethodError เพราะไม่มีเมธอด write บน Computer

undefined method `write' for #<Computer:0x000055c2e8f7d310> (NoMethodError)

คลาส Computer ไม่รู้ว่าคุณหมายถึงอะไรด้วย write

เว้นแต่…

คุณสร้างเมธอด write!

วิธีทำ:

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

เราส่ง request ต่อไปให้ออบเจกต์ @memory

นั่นคือ method delegation

Note: สิ่งนี้ทำให้เมธอดเหล่านี้เป็นส่วนของ public interface (พร้อมให้ทุกคนใช้) และคุณไม่ได้อยากอย่างนั้นเสมอไป

มี shortcut สำหรับ method delegation ไหม?

มีครับ!

มา看看…

วิธีใช้ Forwardable Module

ตอนนี้:

คุณใช้โมดูล Forwardable ที่มาพร้อม Ruby เพื่อนิยาม delegator methods

มันทำงานแบบนี้:

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

สิ่งนี้ช่วยให้คุณลบเมธอดที่สร้างก่อนหน้านี้ออก และมันจะทำสิ่งเดียวกัน

Forwardable จะจัดการ method arguments (รวมถึง blocks!) ให้คุณ ไม่ต้องกังวลเรื่องนั้น

สะดวกมากใช่ไหม? 🙂

วิธีใช้ Rails Delegate Method

หากคุณใช้ Rails หรือ ActiveSupport gem เพียงอย่างเดียว คุณเข้าถึงเมธอด delegate ได้

มันทำงานแบบนี้:

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

เมธอด delegate รับอาร์กิวเมนต์ prefix ซึ่งอนุญาตให้คุณเพิ่ม prefix ให้ชื่อเมธอด

ตัวอย่าง:

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

ผลลัพธ์เป็นสองเมธอด:

  • memory_read
  • memory_write

วิธี Delegate ทุกอย่างด้วย SimpleDelegator

เทคนิคที่เรียนรู้ไปใช้ forward หรือ delegate เมธอดเฉพาะ

แต่หากอยาก wrap ออบเจกต์ และ expose ทุกเมธอดของมัน…

คุณใช้คลาส SimpleDelegator!

วิธีทำ:

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

ตอนนี้ CoolArray พฤติกรรมเหมือนออบเจกต์ที่คุณส่งให้ new

ทำไมถึงมีประโยชน์?

คุณเพิ่มเมธอดใหม่ให้ออบเจกต์นี้ได้ โดยไม่ต้องเปลี่ยนคลาสต้นฉบับ

วิดีโอสอน

สรุป

คุณเรียนรู้เกี่ยวกับ object composition ใน Ruby และวิธี delegate เมธอดด้วยเทคนิคต่างๆ แล้ว!

หากเพลิดเพลินกับบทความนี้กรุณา แชร์ ให้เพื่อน Ruby ของคุณ

ขอบคุณที่อ่าน 🙂