توسيع الكائنات
جزء من قسم البرمجة كائنية التوجه في رحلة Ruby على Coddy. الدرس 28 من 57.
تضيف extend أساليب الوحدة إلى كائن واحد بدلًا من إضافتها إلى جميع النسخ. تؤدي إضافة الامتداد إلى فئة إلى إضافة الأساليب إلى كائن الفئة، ولذلك تصبح أساليب فئة:
module Describable
def describe
"#{name} has #{instance_methods(false).size} methods"
end
end
class Dog
extend Describable
def bark
"Woof"
end
def sit
"sits"
end
end
puts Dog.describeالناتج:
Dog has 2 methodsيمكن لوحدة مستخدمة مع extend أن تحتفظ بالحالة في متغيرات مثيلات الصنف. ويحصل كل صنف يمددها على نسخة خاصة به، بوصفها متغيرات مثيلات الصنف:
module Counted
def created
@created ||= 0
end
def record
@created = created + 1
end
end
class Order
extend Counted
end
class Invoice
extend Counted
end
Order.record
Order.record
Invoice.record
puts "#{Order.created} #{Invoice.created}"الناتج:
2 1تعمل extend أيضًا على كائن واحد. يكتسب ذلك الكائن وحده الأساليب؛ وتبقى النسخ الأخرى من فئته دون تغيير، وتكون is_a? هي true للكائن المُوسَّع فقط:
module Shiny
def polish
"#{self} is shining"
end
end
a = "car"
b = "bike"
a.extend(Shiny)
puts a.polish
puts a.is_a?(Shiny)
puts b.respond_to?(:polish)المخرجات:
car is shining
true
falseتضع الكلمتان المفتاحيتان أساليب الوحدة نفسها في أماكن مختلفة. تجعل include هذه الأساليب أساليبَ مثيلات لفئة، بينما تجعل extend منها أساليبَ للكائن الواحد الذي يتم توسيعه:
class Order
include Printable # order.print_me (كل مثيل)
extend Counted # Order.record (الصنف نفسه)
end
item.extend(Shiny) # item.polish (هذا الكائن فقط)التحدي
سهلأكمل الوحدة البرمجية Registry التي تستخدمها الأصناف مع extend. تضيف register(name) اسمًا إلى القائمة الخاصة بالصنف، المحفوظة في @entries (والتي تُنشأ عند أول استخدام)، وتُرجع Plugin registered x؛ أما الاسم الموجود مسبقًا فتُرجع له Plugin already has x. تُرجع entries القائمة، بينما تُرجع count حجمها. يعمل كل من Plugin وTheme على توسيع Registry ويحتفظ كل منهما بقائمة منفصلة.
يقرأ الكود المزوَّد أسطرًا بالصيغة plugin name أو theme name، ويستدعي register على الصنف المطابق ثم يطبع الرد. وأخيرًا يطبع plugins: a, b (2) وthemes: ...، أو none (0) للقائمة الفارغة.
ضع كودك في registry.rb وplugin.rb وtheme.rb. يحتوي main.rb على كود الإدخال/الإخراج المزوَّد، ولا يمكن تعديله.
جرّب بنفسك
require_relative 'registry'
require_relative 'plugin'
require_relative 'theme'
# كود الإدخال/الإخراج المُزوَّد: أبقِه كما هو
input = []
while (line = gets)
input << line.chomp
end
input.each do |line|
kind, name = line.split
target = kind == "plugin" ? Plugin : Theme
puts target.register(name)
end
[["plugins", Plugin], ["themes", Theme]].each do |label, klass|
list = klass.entries.empty? ? "none" : klass.entries.join(", ")
puts "#{label}: #{list} (#{klass.count})"
end
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
1الفئات والكائنات
العمل مع الملفاتتعريف الفئاتمتغيرات النسخةالأساليب و selfto_s و inspectمراجعة - بطاقة المكتبة7تعدد الأشكال والكتابة بأسلوب البطة
تعدد الأشكالالكتابة بأسلوب البطةالأساليب المجردةالحالات والفئاتمراجعة - طرق الدفع3أساليب ومتغيرات الأصناف
أساليب الأصنافمتغيرات كائنات الأصنافالثوابتأساليب الإنشاءمراجعة - رموز القسائمتدرّب بنفسك: مترجم Ruby عبر الإنترنت