Menu
CoddyTech

复习:自动售货机

本课属于 Coddy Ruby 学习旅程的“面向对象编程”单元。第 21 课,共 57 课。

challenge icon

挑战

中等

创建一台自动售货机,并定义错误类 UnknownProduct、SoldOut 和 NotEnoughCredit,它们都继承自 StandardError。VendingMachine.new(stock) 接收一个哈希 { "cola" => [150, 2] }(价格以分为单位,后面是数量)。credit 可以读取,但只能通过私有的 setter 设置。insert(cents) 会增加余额。buy(name) 按顺序抛出 UnknownProduct(no such product: tea)、SoldOut(cola is sold out)或 NotEnoughCredit(cola costs 1.50, credit 1.00);否则,它会从库存中取出一件商品,扣除价格并返回名称。refund 会退还余额,并将其设为 0。私有辅助方法 money(cents) 会将金额格式化为 1.50。

提供的代码会从第一行读取库存(cola:150:2,chips:90:1),然后读取命令 insert n、buy name 或 refund。它会输出 credit 2.00、bought cola、refund 0.50 或错误消息,最后尝试从外部设置 credit,并输出 credit is protected。

你的代码应写在 unknown_product.rb、sold_out.rb、not_enough_credit.rb 和 vending_machine.rb 中。main.rb 存放提供的输入/输出代码,不能编辑。

亲手试试

require_relative 'unknown_product'
require_relative 'sold_out'
require_relative 'not_enough_credit'
require_relative 'vending_machine'

# 已提供的输入输出代码:保持原样
input = []
while (line = gets)
  input << line.chomp
end
stock = input[0].split(",").to_h do |entry|
  name, price, count = entry.split(":")
  [name, [price.to_i, count.to_i]]
end
machine = VendingMachine.new(stock)
input.drop(1).each do |line|
  command, arg = line.split
  begin
    case command
    when "insert"
      machine.insert(arg.to_i)
      puts format("credit %.2f", machine.credit / 100.0)
    when "buy"
      puts "bought #{machine.buy(arg)}"
    else
      puts format("refund %.2f", machine.refund / 100.0)
    end
  rescue UnknownProduct, SoldOut, NotEnoughCredit => e
    puts e.message
  end
end
begin
  machine.credit = 500
  puts "credit changed"
rescue NoMethodError
  puts "credit is protected"
end

面向对象编程中的所有课

自己练习: Ruby 在线编译器