الوحدات وinclude
جزء من قسم البرمجة كائنية التوجه في رحلة Ruby على Coddy. الدرس 27 من 57.
الوحدة module هي مجموعة مُسمّاة من الأساليب. لا يمكنها إنشاء كائنات، لكن يمكن للصنف include أن يضمّها، وعندها يمتلك كل مثيل أساليب الوحدة كما لو أن الصنف عرّفها. يُسمّى هذا mixin:
module Greetable
def greet
"Hello, I am #{name}"
end
end
class Person
include Greetable
attr_reader :name
def initialize(name)
@name = name
end
end
puts Person.new("Ada").greetالناتج:
Hello, I am Adaيمكن لأساليب الوحدة استدعاء الأساليب التي يوفرها الصنف، مثل name أعلاه. لذلك يمكن لوحدة واحدة أن تخدم أصنافًا مختلفة تمامًا، ما دام كل صنف منها يوفر ما تستخدمه الوحدة:
module Greetable
def greet
"Hello, I am #{name}"
end
end
class Robot
include Greetable
def name
"R2"
end
end
class City
include Greetable
def name
"Paris"
end
end
puts Robot.new.greet
puts City.new.greetالناتج:
Hello, I am R2
Hello, I am Parisللفئة فئةٌ فائقة واحدة فقط، ولكن يمكنها تضمين أي عدد من الوحدات. تسأل include? عمّا إذا كانت الفئة تتضمن وحدةً ما، وتظهر الوحدة في ancestors مباشرةً بعد الفئة، وهو المكان الذي تبحث فيه Ruby عن أساليبها:
module Swimmer
def swim
"swimming"
end
end
module Flyer
def fly
"flying"
end
end
class Duck
include Swimmer
include Flyer
end
d = Duck.new
puts "#{d.swim}, #{d.fly}"
puts Duck.include?(Flyer)
p Duck.ancestors.take(3)الناتج:
swimming, flying
true
[Duck, Flyer, Swimmer]تجمع الوحدات أيضًا الفئات والثوابت ذات الصلة تحت اسم واحد، وهو مساحة أسماء، بحيث لا تتعارض الأسماء. إن Shop::Item وGame::Item فئتان مختلفتان:
module Shop
TAX = 0.2
class Item
def label
"shop item, tax #{TAX}"
end
end
end
puts Shop::Item.new.label
puts Shop::TAXالناتج:
shop item, tax 0.2
0.2التحدي
سهلأكمل الوحدات والأصناف. تُرجع Greetable#greet القيمة Hello, I am Ada باستخدام name للكائن. تضيف Walkable#walk(steps) عدد الخطوات إلى عدّاد محفوظ في @steps (بدءًا من nil في المرة الأولى)، وتُرجع Ada walked 30 steps، أي الإجمالي التراكمي. يضمّن Person كلتا الوحدتين؛ بينما يضمّن Robot الوحدة Greetable فقط، ويكون اسمه R- متبوعًا برقم تسلسلي.
ينشئ الكود المزوَّد شخصًا وروبوتًا من السطر الأول (Ada 7)، ثم ينفّذ الأوامر greet p أو greet r أو walk 10 (للشخص)، ويطبع نتيجة كل أمر، وأخيرًا يطبع robot walks: false.
ضع الكود الخاص بك في greetable.rb وwalkable.rb وperson.rb وrobot.rb. يحتوي main.rb على كود الإدخال/الإخراج المزوَّد، ولا يمكن تعديله.
جرّب بنفسك
require_relative 'greetable'
require_relative 'walkable'
require_relative 'person'
require_relative 'robot'
# كود الإدخال/الإخراج المُزوَّد: أبقِه كما هو
input = []
while (line = gets)
input << line.chomp
end
name, serial = input[0].split
person = Person.new(name)
robot = Robot.new(serial)
input.drop(1).each do |line|
command, arg = line.split
if command == "walk"
puts person.walk(arg.to_i)
else
target = arg == "p" ? person : robot
puts target.greet
end
end
puts "robot walks: #{Robot.include?(Walkable)}"
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
1الفئات والكائنات
العمل مع الملفاتتعريف الفئاتمتغيرات النسخةالأساليب و selfto_s و inspectمراجعة - بطاقة المكتبة7تعدد الأشكال والكتابة بأسلوب البطة
تعدد الأشكالالكتابة بأسلوب البطةالأساليب المجردةالحالات والفئاتمراجعة - طرق الدفع3أساليب ومتغيرات الأصناف
أساليب الأصنافمتغيرات كائنات الأصنافالثوابتأساليب الإنشاءمراجعة - رموز القسائمتدرّب بنفسك: مترجم Ruby عبر الإنترنت