פולימורפיזם
חלק מהיחידה תכנות מונחה עצמים במסלול ה-Ruby של Coddy. שיעור 32 מתוך 57.
פולימורפיזם פירושו שקריאה אחת למתודה פועלת על אובייקטים ממחלקות שונות, וכל אובייקט משיב בדרך משלו. קוד שעובר בלולאה על צורות קורא ל־area בכל אחת מהן בלי לבדוק מאיזה סוג צורה היא:
class Shape
def to_s
format("%s %.2f", self.class.name.downcase, area)
end
end
class Circle < Shape
def initialize(r)
@r = r
end
def area
3.14159 * @r * @r
end
end
class Square < Shape
def initialize(side)
@side = side
end
def area
@side * @side
end
end
shapes = [Circle.new(1), Square.new(3)]
shapes.each { |s| puts s }
puts format("total %.2f", shapes.sum(&:area))פלט:
circle 3.14
square 9.00
total 12.14ללא פולימורפיזם, הקוד הקורא צריך לבדוק את הסוג של כל אובייקט ולחזור על הבדיקה הזאת בכל מקום שבו ההבדל חשוב. עם פולימורפיזם, ההבדל נמצא בתוך כל מחלקה:
# ללא פולימורפיזם
case shape.kind
when "circle" then 3.14159 * shape.r ** 2
when "square" then shape.side ** 2
end
# עם פולימורפיזם
shape.areaהוספת סוג חדש של אובייקט אינה דורשת שינוי בקוד הקורא: תת־מחלקה חדשה עם area משלה פועלת בכל לולאה קיימת:
class Shape
def describe
"area #{area}"
end
end
class Square < Shape
def area
4
end
end
class Triangle < Shape
def area
6
end
end
[Square.new, Triangle.new].each { |s| puts s.describe }פלט:
area 4
area 6to_s היא דוגמה יומיומית: puts קוראת לה עבור כל אובייקט, וכל מחלקה משיבה באופן שונה. המחלקות שלך מצטרפות בכך שהן מגדירות to_s משלהן:
class Coin
def to_s
"a coin"
end
end
[42, "text", nil, [1, 2], Coin.new].each { |x| puts "[#{x}]" }פלט:
[42]
[text]
[]
[[1, 2]]
[a coin]אתגר
קלהשלימו את הצורות. Shape#to_s מחזירה את circle: 3.14, את שם המחלקה באותיות קטנות ואת השטח עם שתי ספרות אחרי הנקודה העשרונית, וכל מחלקת משנה מספקת area: Circle.new(r) (השתמשו ב־3.14159 עבור פאי), Rectangle.new(w, h) ו־Triangle.new(base, height).
הקוד שסופק קורא שורות circle 1, rectangle 2 3 או triangle 4 5, מדפיס כל צורה, ואז total: 22.14 ו־largest: rectangle: 6.00, תוך שימוש רק ב־to_s וב־area.
הקוד שלכם ייכתב בקבצים shape.rb, circle.rb, rectangle.rb ו־triangle.rb. הקובץ main.rb מכיל את קוד הקלט/פלט שסופק ואי אפשר לערוך אותו.
נסו בעצמכם
require_relative 'shape'
require_relative 'circle'
require_relative 'rectangle'
require_relative 'triangle'
# קוד קלט/פלט שסופק: יש להשאיר אותו כפי שהוא
input = []
while (line = gets)
input << line.chomp
end
kinds = { "circle" => Circle, "rectangle" => Rectangle, "triangle" => Triangle }
shapes = input.map do |line|
kind, *numbers = line.split
kinds[kind].new(*numbers.map(&:to_f))
end
shapes.each { |s| puts s }
puts format("total: %.2f", shapes.sum(&:area))
puts "largest: #{shapes.max_by(&:area)}"
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
3מתודות ומשתנים של מחלקה
מתודות של מחלקהמשתני מופע של מחלקהקבועיםמתודות ליצירת מופעיםסיכום – קודי קופוןתרגלו בעצמכם: קומפיילר Ruby אונליין