المعيّنات الخاصة
جزء من قسم البرمجة كائنية التوجه في رحلة 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يُستدعى المُعيّن الخاص باستخدام 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إن المرور عبر مُعيّن خاص بدلًا من إسناد @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 من الخارج، ولكن لا يمكن تعيينه إلا من خلال أداة تعيين خاصة، وتبدأ قيمته من 0. تضيف earn(amount) قيمةً إليه. تخصم spend(amount) منه وتُرجع true، أو تُرجع false من دون إجراء أي تغيير عندما يكون الرصيد منخفضًا جدًا. تُرجع history عدد التغييرات الناجحة، وتبقى هي الأخرى محميةً خلف أداة تعيين خاصة.
يقرأ الكود المزوَّد الأوامر +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
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
1الفئات والكائنات
العمل مع الملفاتتعريف الفئاتمتغيرات النسخةالأساليب و selfto_s و inspectمراجعة - بطاقة المكتبة7تعدد الأشكال والكتابة بأسلوب البطة
تعدد الأشكالالكتابة بأسلوب البطةالأساليب المجردةالحالات والفئاتمراجعة - طرق الدفع3أساليب ومتغيرات الأصناف
أساليب الأصنافمتغيرات كائنات الأصنافالثوابتأساليب الإنشاءمراجعة - رموز القسائمتدرّب بنفسك: مترجم Ruby عبر الإنترنت