סַטֶּרִים פרטיים
חלק מהיחידה תכנות מונחה עצמים במסלול ה-Ruby של Coddy. שיעור 19 מתוך 57.
לעיתים קרובות, ערך צריך להיות קריא לכולם, אך ניתן לשינוי רק על ידי האובייקט. attr_reader מספק קורא ציבורי, ו־private attr_writer מספק מגדיר שרק האובייקט יכול להשתמש בו. הדבר עובד מפני ש־attr_writer מחזיר את שמות המתודות שהוא מגדיר:
class Wallet
attr_reader :balance
def initialize
self.balance = 0
end
def earn(amount)
self.balance = balance + amount
end
private attr_writer :balance
end
w = Wallet.new
w.earn(30)
puts w.balance
begin
w.balance = 1_000_000
rescue NoMethodError => e
puts e.message
endפלט:
30
private method `balance=' called for an instance of Walletל־setter פרטי קוראים עם self. בתוך המחלקה, המקבל היחיד ש־Ruby מאפשרת עבור מתודות פרטיות. ללא self. ההשמה הייתה יוצרת רק משתנה מקומי:
class Lamp
attr_reader :on
def initialize
self.on = false
end
def toggle
self.on = !on
self
end
private
attr_writer :on
end
puts Lamp.new.toggle.toggle.toggle.onפלט:
trueשימוש ב-setter פרטי במקום השמה ישירה ל-@balance מרכז את הכללים במקום אחד, למשל בדיקה שהערך תקין:
class Tank
attr_reader :litres
def initialize(capacity)
@capacity = capacity
self.litres = 0
end
def fill(amount)
self.litres = litres + amount
end
def drain(amount)
self.litres = litres - amount
end
private
def litres=(value)
@litres = value.clamp(0, @capacity)
end
end
t = Tank.new(50)
t.fill(80)
puts t.litres
t.drain(70)
puts t.litresפלט:
50
0private attr_accessor :history מסתיר גם את הקורא וגם את הקובע, עבור מצב פנימי שקוד חיצוני לא אמור אפילו לראות:
class Editor
def initialize
self.history = []
end
def type(text)
history << text
end
private attr_accessor :history
endאתגר
קלהשלימו את המחלקה Wallet. אפשר לקרוא את balance מבחוץ, אך ניתן להגדיר אותו רק באמצעות setter פרטי, והוא מתחיל ב־0. earn(amount) מוסיפה לו. spend(amount) מפחיתה ממנו ומחזירה true, או מחזירה false ללא שינוי כאשר היתרה נמוכה מדי. history מחזירה את מספר השינויים המוצלחים, וגם היא נשמרת מאחורי setter פרטי.
הקוד שסופק קורא פקודות +n או -n, ומדפיס balance 30 אחרי כל אחת מהן, או declined כאשר הוצאה נכשלת. לאחר מכן הוא מדפיס changes: 2 ומנסה לבצע wallet.balance = 1000000, ומדפיס cannot set balance כאשר Ruby מסרבת.
הקוד שלך צריך להופיע בקובץ wallet.rb. הקובץ main.rb מכיל את קוד הקלט/פלט שסופק, ואי אפשר לערוך אותו.
נסו בעצמכם
require_relative 'wallet'
# קוד הקלט/פלט שסופק: יש להשאיר אותו כפי שהוא
input = []
while (line = gets)
input << line.chomp
end
wallet = Wallet.new
input.each do |cmd|
amount = cmd[1..].to_i
if cmd.start_with?("+")
wallet.earn(amount)
puts "balance #{wallet.balance}"
elsif wallet.spend(amount)
puts "balance #{wallet.balance}"
else
puts "declined"
end
end
puts "changes: #{wallet.history}"
begin
wallet.balance = 1_000_000
puts "balance set"
rescue NoMethodError
puts "cannot set balance"
end
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
3מתודות ומשתנים של מחלקה
מתודות של מחלקהמשתני מופע של מחלקהקבועיםמתודות ליצירת מופעיםסיכום – קודי קופוןתרגלו בעצמכם: קומפיילר Ruby אונליין