Menu
Coddy logo textTech

Константы

Часть раздела Объектно-ориентированное программирование путешествия по Ruby на Coddy. Урок 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). initialize(total, method) вызывает исключение ArgumentError с сообщением unknown shipping: drone, если метод не является ключом RATES. shipping возвращает 0 для итоговых сумм от FREE_FROM и выше, а в остальных случаях — соответствующую ставку, а 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