Menu
CoddyTech

private setter

Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan Ruby di Coddy. Pelajaran 19 dari 57.

Sering kali, sebuah nilai sebaiknya dapat dibaca oleh semua orang, tetapi hanya dapat diubah oleh object. attr_reader menyediakan pembaca publik, sedangkan private attr_writer menyediakan setter yang hanya dapat digunakan oleh object. Ini berfungsi karena attr_writer mengembalikan nama method yang ditentukannya:

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

Output:

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

Setter privat dipanggil dengan self. di dalam class, satu-satunya receiver yang diterima Ruby untuk method privat. Tanpa self., assignment hanya akan membuat variabel lokal:

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

Output:

true

Menggunakan setter privat alih-alih menetapkan @balance secara langsung membuat satu tempat untuk aturan, seperti pemeriksaan untuk memastikan nilainya valid:

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

Output:

50
0

private attr_accessor :history menyembunyikan reader dan setter sekaligus, untuk state internal yang bahkan tidak seharusnya dilihat oleh kode di luar:

class Editor
  def initialize
    self.history = []
  end

  def type(text)
    history << text
  end

  private attr_accessor :history
end
challenge icon

Tantangan

Mudah

Lengkapi class Wallet. balance dapat dibaca dari luar, tetapi hanya dapat diatur melalui setter privat, dimulai dari 0. earn(amount) menambahkannya. spend(amount) menguranginya dan mengembalikan true, atau mengembalikan false tanpa perubahan ketika saldo terlalu rendah. history mengembalikan jumlah perubahan yang berhasil, dan juga dilindungi oleh setter privat.

Kode yang disediakan membaca perintah +n atau -n, lalu mencetak balance 30 setelah setiap perintah, atau declined saat pengeluaran gagal. Lalu kode mencetak changes: 2 dan mencoba wallet.balance = 1000000, lalu mencetak cannot set balance saat Ruby menolaknya.

Tulis kodemu di wallet.rb. main.rb berisi kode input/output yang disediakan dan tidak boleh diedit.

Coba sendiri

require_relative 'wallet'

# Kode input/output yang disediakan: biarkan apa adanya
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 iconUji dirimu

Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.

Semua pelajaran di Pemrograman Berorientasi Objek

Latihan sendiri: Compiler Ruby online