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

วิธีการ Hook ที่สืบทอดมาใน Ruby - และบทเรียนการเลี้ยงดูเพิ่มเติม

สวัสดีเด็ก ๆ และผู้ปกครอง ahem Rubyists ในบทความก่อนหน้านี้ เราได้เจาะลึกถึงห่วงโซ่ของบรรพบุรุษ ในโพสต์ของวันนี้ เราจะเจาะลึกการเลี้ยงลูกและการสืบทอด เราจะสำรวจวิธีการเบ็ดที่สืบทอดมาและมองหาการป้องกันการสืบทอด

เมื่อเด็ก ๆ สืบทอด 101:วิธีเบ็ดที่สืบทอดมา

เริ่มต้นด้วยการดูว่าการประกาศความเป็นพ่อแม่เป็นอย่างไร Ruby ให้วิธีการโต้ตอบกับคลาสที่เรียบร้อยเมื่อมีการประกาศเป็นพาเรนต์ของคลาสอื่น

class Parent
  def self.inherited(subclass)
    puts "#{subclass} inherits from Parent"
  end
end
 
class Child < Parent
end

การเรียกใช้รหัสนี้จะพิมพ์ว่า "Child inherits from Parent" เป็น Parent.inherited เมธอดจะถูกเรียกเมื่อ Child คลาสที่สืบทอดมาจาก Parent . โปรดทราบว่าเมธอดนี้ใช้คลาสย่อยเป็นพารามิเตอร์—Child ในกรณีของเรา กลไกนี้อนุญาตให้คุณโต้ตอบกับคลาสพาเรนต์เพื่อกำหนดชุดของพฤติกรรมได้ก็ต่อเมื่อได้รับการสืบทอดมา โดยพฤติกรรม ในบริบทนี้ เราหมายถึงการปรับเปลี่ยน กำหนดหรือลบตัวแปร เมธอด และค่าคงที่ในการสืบทอดหรือคลาสที่สืบทอดมา

ตอนนี้ มากำหนด parent_name วิธี on-the-fly:

class Parent
  def self.inherited(subclass)
    subclass.define_method :parent_name do
      "Daddy"
    end
  end
end
 
class Child < Parent
end
 
Child.new.parent_name # => "Daddy"

ที่นี่ เรากำหนดวิธีการใน Child class เมื่อสืบทอดมาจาก Parent คลาส แต่ไม่เพิ่มเมธอดนั้นโดยตรงใน Parent ระดับ. แต่จะกำหนดก็ต่อเมื่อคลาสอื่นสืบทอดมาจาก Parent .

เอาล่ะ เราครอบคลุมทฤษฎีแล้ว ตอนนี้เรามาดูตัวอย่างที่สมจริงมากขึ้นในชีวิตของ Rubyist

ป้องกันการสืบทอดคลาส

ใน Ruby on Rails การย้ายฐานข้อมูลจะถูกจัดการโดย ActiveRecord::Migration ระดับ. มาลองสืบทอดโดยตรงจากคลาสนี้กัน

class AddFirstnameToUsers < ActiveRecord::Migration
end
 
# => StandardError (Directly inheriting from ActiveRecord::Migration is not supported..)

ข้อผิดพลาดนี้เกิดขึ้นเนื่องจาก Ruby on Rails มีกลไกที่ป้องกันไม่ให้เราสืบทอดจากคลาสนี้ เหตุใด Ruby on Rails จึงใช้กลไกนี้

การโยกย้ายนั้นเชื่อมโยงกับ Ruby on Rails เวอร์ชันเฉพาะอย่างยิ่ง อันที่จริง API ที่มีให้โดยคลาสนี้สามารถเปลี่ยนแปลงได้เล็กน้อยระหว่าง 2 เวอร์ชัน ดังนั้น เพื่อหลีกเลี่ยงการทำลายการย้ายข้อมูลเมื่อคุณอัพเกรด Ruby on Rails เฟรมเวิร์กจะบังคับให้คุณเลือกเวอร์ชันเฉพาะของคลาส ActiveRecord::Migration ซึ่งจะทำให้การย้ายข้อมูลของคุณเป็นไปอย่างราบรื่น

class AddFirstnameToUsers < ActiveRecord::Migration[4.2]
end

ในตัวอย่างข้างต้น การย้ายข้อมูลของเราเชื่อมโยงกับ ActiveRecord::Migration API ที่มาพร้อมกับ Ruby on Rails เวอร์ชัน 4.2 ดังนั้น แม้ว่าเราจะอัปเกรดแอปพลิเคชันของเราเป็นเวอร์ชัน 5.0 การย้ายข้อมูลของเราก็ยังทำงานได้อย่างราบรื่นเพราะจะยังทำงานด้วย ActiveRecord::Migration เวอร์ชัน 4.2 API.

วิธีการป้องกันการสืบทอดทำงานอย่างไร

ตอนนี้เราเข้าใจแล้วว่าทำไม ป้องกันมรดกไว้ที่นี่ มาดูกันว่า อย่างไร ActiveRecord::Migration this นี้ ป้องกันการสืบทอด ตรรกะทั้งหมดถูกกำหนดไว้ใน ActiveRecord::Migration.inherited วิธีการ

class AddFirstnameToUsers < ActiveRecord::Migration[4.2]
end

เมื่อ AddFirstnameToUsers . ของเรา คลาสที่สืบทอดมาจาก ActiveRecord::Migration , ActiveRecord::Migration.inherited เรียกวิธีเบ็ด

module ActiveRecord
  class Migration
    def self.inherited(subclass) #:nodoc:
      super
      if subclass.superclass == Migration
        raise StandardError, "Directly inheriting from ActiveRecord::Migration is not supported. " \
          "Please specify the Rails release the migration was written for:\n" \
          "\n" \
          "  class #{subclass} < ActiveRecord::Migration[4.2]"
      end
    end
  end
end

อย่างที่เราเห็น วิธี hook นี้จะตรวจสอบว่า subclass (AddFirstnameToUsers ) สืบทอดโดยตรงจาก ActiveRecord::Migration . หากเป็นเช่นนั้น จะเกิดข้อผิดพลาดขึ้น นี่เป็นจุดเริ่มต้นที่สมบูรณ์แบบสำหรับการควบคุมมรดก

บทสรุป

วันนี้เราได้กล่าวถึงพื้นฐานของการสืบทอดและการป้องกันการรับมรดก เราครอบคลุมวิธีการของ hook ที่สืบทอดมา และเห็นว่ามันจะมีประโยชน์มากเมื่อโต้ตอบกับคลาสที่สืบทอด/สืบทอดมาได้ทันที

ในสภาพแวดล้อมจริง โปรดระวังเมื่อเล่นกับมรดก ระวังให้มากเมื่อคุณลบหรือแทนที่วิธีการหรือคลาสที่มีอยู่ ซึ่งอาจส่งผลให้เกิดผลข้างเคียงที่ไม่พึงประสงค์บางอย่าง ลูกๆ อาจเลิกเรียกคุณว่าพ่อ

Et Voila นี่เป็นการสรุปโพสต์ของเราสำหรับวันนี้!