Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

الوحدات و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
challenge icon

التحدي

سهل

أكمل الوحدات والأصناف. تُرجع 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)}"
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس البرمجة كائنية التوجه

تدرّب بنفسك: مترجم Ruby عبر الإنترنت