Menu
CoddyTech

Melindungi Status

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

Sebuah object seharusnya menolak permintaan yang akan merusak statusnya. raise menghentikan method sebelum terjadi perubahan apa pun. Nama class error buatanmu menjelaskan masalahnya secara spesifik; < StandardError menjadikan class tersebut sejenis error (pewarisan, bab 5):

class InsufficientFunds < StandardError
end

class Account
  attr_reader :balance

  def initialize(balance)
    @balance = balance
  end

  def withdraw(amount)
    raise InsufficientFunds, "only #{balance} available" if amount > balance

    @balance -= amount
  end
end

account = Account.new(50)
begin
  account.withdraw(80)
rescue InsufficientFunds => e
  puts "#{e.class}: #{e.message}"
end
puts account.balance

Output:

InsufficientFunds: only 50 available
50

Kelas error yang terpisah memungkinkan pemanggil menangani setiap masalah secara berbeda, dengan satu rescue untuk setiap kelas. Deklarasikan kelas error sebelum kelas yang memunculkannya:

class InvalidAmount < StandardError
end

class LimitReached < StandardError
end

class Card
  def charge(amount)
    raise InvalidAmount, "amount must be positive" unless amount.positive?
    raise LimitReached, "limit is 100" if amount > 100

    "charged #{amount}"
  end
end

[40, -5, 500].each do |amount|
  puts Card.new.charge(amount)
rescue InvalidAmount => e
  puts "fix the input: #{e.message}"
rescue LimitReached => e
  puts "try later: #{e.message}"
end

Output:

charged 40
fix the input: amount must be positive
try later: limit is 100

freeze membuat object hanya dapat dibaca: setelah itu, setiap perubahan pada variabel instansinya memunculkan FrozenError, sedangkan pembacaan tetap berfungsi. frozen? memberi tahu apakah sebuah object dibekukan:

class Point
  attr_accessor :x

  def initialize(x)
    @x = x
  end
end

pt = Point.new(1).freeze
puts pt.frozen?
begin
  pt.x = 2
rescue FrozenError => e
  puts e.class
end
puts pt.x

Output:

true
FrozenError
1

Reader yang mengembalikan array internal menyerahkan array yang sebenarnya, sehingga kode di luar object dapat mengubahnya. Kembalikan salinan yang dibekukan dengan @items.dup.freeze, atau @items.dup, agar object tetap mengendalikan datanya sendiri:

class Playlist
  def initialize
    @songs = []
  end

  def add(song)
    @songs << song
  end

  def songs
    @songs.dup.freeze
  end
end

list = Playlist.new
list.add("Intro")
begin
  list.songs << "Hack"
rescue FrozenError
  puts "songs are read-only"
end
p list.songs

Output:

songs are read-only
["Intro"]
challenge icon

Tantangan

Mudah

Deklarasikan class error InvalidAmount dan InsufficientFunds, keduanya merupakan subclass StandardError, lalu lengkapi Account. deposit(amount) dan withdraw(amount) memunculkan InvalidAmount dengan amount must be positive untuk jumlah di bawah 1. withdraw memunculkan InsufficientFunds dengan balance is only 20 ketika jumlahnya lebih besar daripada saldo. Tidak ada yang berubah ketika error dimunculkan.

Kode yang disediakan membaca perintah dep n atau wd n dan mencetak balance 70 setelah setiap perintah, invalid: amount must be positive untuk InvalidAmount, dan refused: balance is only 20 untuk InsufficientFunds.

Kodemu ditulis di invalid_amount.rb, insufficient_funds.rb, dan account.rb. main.rb berisi kode input/output yang disediakan dan tidak boleh diedit.

Coba sendiri

require_relative 'invalid_amount'
require_relative 'insufficient_funds'
require_relative 'account'

# Kode input/output yang disediakan: biarkan apa adanya
input = []
while (line = gets)
  input << line.chomp
end
account = Account.new
input.each do |line|
  action, amount = line.split
  begin
    action == "dep" ? account.deposit(amount.to_i) : account.withdraw(amount.to_i)
    puts "balance #{account.balance}"
  rescue InvalidAmount => e
    puts "invalid: #{e.message}"
  rescue InsufficientFunds => e
    puts "refused: #{e.message}"
  end
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