常量
本课属于 Coddy Ruby 学习旅程的“面向对象编程”单元。第 14 课,共 57 课。
常量以大写字母开头,按照惯例使用大写字母书写。在类体中定义后,可以在该类的每个方法中按名称使用。在类外部,写作 ClassName::NAME:
class Account
MIN_BALANCE = -100
def self.allowed?(balance)
balance >= MIN_BALANCE
end
end
puts Account::MIN_BALANCE
puts Account.allowed?(-50)
puts Account.allowed?(-150)输出:
-100
true
false常量适合存放整个类共用的固定数据,例如限制值或查找表。对哈希常量使用 fetch 时,如果键不存在,会引发 KeyError,而不是静默地返回 nil:
class Shipping
RATES = { "standard" => 5, "express" => 12 }.freeze
def self.cost(method)
RATES.fetch(method)
end
end
puts Shipping.cost("express")
begin
Shipping.cost("drone")
rescue KeyError => e
puts e.message
end输出:
12
key not found: "drone"如果不打印警告,Ruby 就不能让常量名指向新的对象,但它所持有的对象仍然可以修改。freeze 会让对象本身变为只读,因此修改会引发 FrozenError:
class Palette
COLORS = ["red", "green"].freeze
end
begin
Palette::COLORS << "blue"
rescue FrozenError => e
puts e.message
end
p Palette::COLORS
p Palette::COLORS.frozen?输出:
can't modify frozen Array: ["red", "green"]
["red", "green"]
true根据值的行为来选择。永远不会变化的值应使用冻结常量;程序运行时会变化的状态(例如计数器)应使用类实例变量:
class Ticket
PREFIX = "TK" # 固定不变:常量
@issued = 0 # 会变化:类实例变量
def self.next_code
@issued += 1
"#{PREFIX}-#{@issued}"
end
end挑战
简单补全类 Order。它包含常量 RATES(一个冻结的哈希:standard 的费用为 5,express 为 12,pickup 为 0)和 FREE_FROM(50)。如果 method 不是 RATES 的键,initialize(total, method) 会引发 ArgumentError,并显示 unknown shipping: drone。当总额达到或超过 FREE_FROM 时,shipping 返回 0,否则返回相应费率;to_s 返回 40.00 + 5 express = 45.00。
提供的代码会使用该常量打印 free from 50,然后读取格式为 total method 的订单行,并打印每个订单或错误消息。
你的代码写在 order.rb 中。main.rb 包含提供的输入/输出代码,不能修改。
亲手试试
require_relative 'order'
# 提供的输入输出代码:保持原样
input = []
while (line = gets)
input << line.chomp
end
puts "free from #{Order::FREE_FROM}"
input.each do |line|
total, method = line.split
begin
puts Order.new(total.to_f, method)
rescue ArgumentError => e
puts e.message
end
end
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Ruby 在线编译器