Menu
CoddyTech

Özel Atayıcılar

Coddy'nin Ruby Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 19 / 57.

Çoğu zaman bir değer herkes tarafından okunabilmeli, ancak yalnızca nesne tarafından değiştirilebilmelidir. attr_reader herkese açık bir okuyucu, private attr_writer ise yalnızca nesnenin kullanabileceği bir ayarlayıcı sağlar. Bunun nedeni attr_writer metodunun tanımladığı metotların adlarını döndürmesidir:

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

Çıktı:

30
private method `balance=' called for an instance of Wallet

Özel bir setter, sınıfın içinde self. ile çağrılır; Ruby'nin özel metotlar için kabul ettiği tek alıcı budur. self. olmadan atama yalnızca yerel bir değişken oluştururdu:

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

Çıktı:

true

@balance'a doğrudan değer atamak yerine özel bir setter üzerinden geçmek, değerin geçerli olup olmadığını kontrol etmek gibi kurallar için tek bir yer sağlar:

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

Çıktı:

50
0

private attr_accessor :history, hem okuyucuyu hem de ayarlayıcıyı gizler; böylece dışarıdaki kodun görmemesi gereken dahili durumu saklar:

class Editor
  def initialize
    self.history = []
  end

  def type(text)
    history << text
  end

  private attr_accessor :history
end
challenge icon

Görev

Kolay

Wallet sınıfını tamamla. balance dışarıdan okunabilir, ancak yalnızca özel bir setter aracılığıyla ayarlanabilir ve başlangıç değeri 0'dır. earn(amount) bu değeri artırır. spend(amount) bu değeri azaltıp true döndürür; bakiye yetersiz olduğunda ise hiçbir değişiklik yapmadan false döndürür. history, yine özel bir setter'ın arkasında tutulan başarılı değişikliklerin sayısını döndürür.

Sağlanan kod +n veya -n komutlarını okur ve her birinin ardından balance 30 yazdırır; harcama başarısız olduğunda ise declined yazdırır. Ardından changes: 2 yazdırır ve wallet.balance = 1000000 atamasını dener; Ruby bu atamayı reddettiğinde cannot set balance yazdırır.

Kodunu wallet.rb dosyasına yaz. main.rb, sağlanan girdi/çıktı kodunu içerir ve düzenlenemez.

Kendin dene

require_relative 'wallet'

# Sağlanan giriş/çıkış kodu: olduğu gibi bırakın
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
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Yönelimli Programlama bölümündeki tüm dersler

Kendi başına pratik yap: Online Ruby derleyicisi