Menu
Coddy logo textTech

Ö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 okunabilir, ancak yalnızca nesne tarafından değiştirilebilir olmalıdır. attr_reader herkese açık okuyucuyu, private attr_writer ise yalnızca nesnenin kullanabileceği bir ayarlayıcıyı sağlar. Bu, attr_writer tanımladığı yöntemlerin adlarını döndürdüğü için çalışır:

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 içinde self. ile çağrılır; bu, Ruby’nin özel metotlar için kabul ettiği tek alıcıdır. 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

Doğrudan @balance atamak yerine özel bir setter üzerinden geçmek, değerin geçerli olup olmadığını kontrol etmek gibi kurallar için tek bir yer olmasını 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, dışarıdaki kodun görmemesi gereken dahili durum için hem okuyucuyu hem de ayarlayıcıyı gizler:

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 başlangıç değeri 0 olacak şekilde yalnızca özel bir setter üzerinden ayarlanabilir. earn(amount) buna ekleme yapar. spend(amount) bakiyeden düşer ve true döndürür; bakiye yetersiz olduğunda ise herhangi bir değişiklik yapmadan false döndürür. history, başarılı değişikliklerin sayısını döndürür ve o da özel bir setter ile korunur.

Sağlanan kod +n veya -n komutlarını okur; her birinden sonra balance 30 yazdırır veya bir harcama başarısız olduğunda declined yazdırır. Ardından changes: 2 yazdırır ve wallet.balance = 1000000 işlemini dener; Ruby bunu reddettiğinde cannot set balance yazdırır.

Kodun wallet.rb dosyasına yazılmalıdır. main.rb sağlanan giriş/çıkış kodunu içerir ve düzenlenemez.

Kendin dene

require_relative 'wallet'

# Sağlanan girdi/çıktı 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