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

การเชี่ยวชาญเมธอดฮุก inherited ของ Ruby: เคล็ดลับขั้นสูงสำหรับนักพัฒนา

สวัสดีเด็กๆ และพ่อแม่ อืม นักพัฒนา Ruby ในบทความก่อนหน้า เราได้ดำดิ่งสู่ ancestry chain ในบทความวันนี้ เราจะดำดิ่งลึกเข้าไปในการเป็นพ่อแม่และการสืบทอด (inheritance) เราจะสำรวจ inherited hook method และดูการป้องกันการสืบทอด

เมื่อลูกสืบทอด 101: The Inherited Hook Method

เริ่มด้วยการดูว่าการเป็นพ่อแม่ถูกประกาศอย่างไร 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 โปรดสังเกตว่าเมธอดนี้รับ subclass เป็นพารามิเตอร์—Child ในกรณีนี้ กลไกนี้ช่วยให้คุณโต้ตอบกับคลาส Parent เพื่อกำหนดชุดพฤติกรรมเฉพาะก็ต่อเมื่อมันถูกสืบทอด โดยพฤติกรรมในบริบทนี้ หมายถึงการแก้ไข กำหนด หรือลบ ตัวแปร เมธอด และค่าคงที่บนคลาสที่สืบทอดหรือถูกสืบทอด

ตอนนี้ มากำหนดเมธอด 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 เมื่อมันสืบทอดจาก Parent แต่โดยไม่เพิ่มเมธอดนั้นโดยตรงไปที่คลาส Parent แทนที่จะเป็นเช่นนั้น มันถูกกำหนดเฉพาะเมื่ออีกคลาสหนึ่งสืบทอดจาก Parent

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

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

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

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

ข้อผิดพลาดนี้ถูก raise เพราะ Ruby on Rails มีกลไกที่ป้องกันไม่ให้เราสืบทอดจากคลาสนี้ ทำไม Ruby on Rails จึง implement กลไกนี้?

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

class AddFirstnameToUsers < ActiveRecord::Migration[4.2] end

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

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

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

class AddFirstnameToUsers < ActiveRecord::Migration[4.2] end

เมื่อคลาส AddFirstnameToUsers ของเราสืบทอดจาก ActiveRecord::Migration เมธอด hook 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 นี้ตรวจสอบว่าคลาสย่อย (AddFirstnameToUsers) สืบทอดโดยตรงจาก ActiveRecord::Migration หากใช่ จะ raise error นี่คือ entry point ที่สมบูรณ์สำหรับการควบคุมการสืบทอด

สรุป

วันนี้ เราครอบคลุมพื้นฐานของการสืบทอดและการป้องกันการสืบทอด เราครอบคลุม inherited hook method และเห็นว่ามันมีประโยชน์มากเมื่อโต้ตอบกับคลาสที่สืบทอด/ถูกสืบทอด on-the-fly

ในการตั้งค่าจริง ให้ระมัดระวังเมื่อเล่นกับการสืบทอด ให้ระมัดระวังมากเมื่อคุณลบหรือ override เมธอดหรือคลาสที่มีอยู่ นี่อาจทำให้เกิด side effects ที่ไม่พึงประสงค์ ลูกๆ อาจหยุดเรียกคุณว่า daddy

Et Voilà บทความวันจบสิ้นสุดที่นี่!