Menu
CoddyTech

常量

本课属于 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
challenge icon

挑战

简单

补全类 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
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: Ruby 在线编译器