สวัสดีเด็ก ๆ และผู้ปกครอง 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 นี่เป็นการสรุปโพสต์ของเราสำหรับวันนี้!