Menu
Coddy logo textTech

מודולים ו-include

חלק מהיחידה תכנות מונחה עצמים במסלול ה-Ruby של Coddy. שיעור 27 מתוך 57.

מודול הוא קבוצה בעלת שם של מתודות. הוא לא יכול ליצור אובייקטים, אבל מחלקה יכולה לבצע בו include, ואז לכל מופע יש את המתודות של המודול כאילו המחלקה הגדירה אותן. זה נקרא מיקסין:

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 אונליין