Menu
Coddy logo textTech

Переменные экземпляра класса

Часть раздела Объектно-ориентированное программирование путешествия по Ruby на Coddy. Урок 13 из 57.

Класс тоже является объектом, поэтому у него могут быть собственные переменные экземпляра. @issued = 0 в теле класса, где self — это класс, принадлежит классу, а не какому-либо экземпляру. Методы класса читают и изменяют её:

class Ticket
  @issued = 0

  def self.issue
    @issued += 1
  end

  def self.issued
    @issued
  end
end

Ticket.issue
Ticket.issue
puts Ticket.issued

Вывод:

2

attr_accessor внутри class << self создаёт геттер и сеттер для класса. Затем экземпляры получают доступ к состоянию класса через self.class, например чтобы подсчитать каждый объект, который создаёт new:

class Robot
  @built = 0

  class << self
    attr_accessor :built
  end

  attr_reader :serial

  def initialize
    self.class.built += 1
    @serial = self.class.built
  end
end

a = Robot.new
b = Robot.new
puts "#{a.serial} #{b.serial} #{Robot.built}"

Вывод:

1 2 2

В Ruby также есть переменные класса, записываемые как @@name. Переменная класса является общей для класса и всех его экземпляров, поэтому методы экземпляра могут обращаться к ней напрямую:

class Player
  @@count = 0

  def initialize
    @@count += 1
  end

  def self.count
    @@count
  end

  def others
    @@count - 1
  end
end

Player.new
last = Player.new
puts Player.count
puts last.others

Вывод:

2
1

Переменная класса также является общей для каждого подкласса (класса, созданного на основе другого класса, глава 5), поэтому подкласс, который присваивает ей значение, изменяет её и для родительского класса. Переменная экземпляра класса остаётся отдельной для каждого класса, поэтому в большинстве кода на Ruby предпочитают именно её:

class Base
  @@kind = "base"
  @label = "base"

  class << self
    attr_reader :label
  end

  def self.kind
    @@kind
  end
end

class Child < Base
  @@kind = "child"
  @label = "child"
end

puts Base.kind
puts Base.label
puts Child.label

Результат:

child
base
child
challenge icon

Задание

Легко

Завершите класс Ticket. Каждый новый билет получает следующий номер, начиная с 1, из счётчика, хранящегося в переменной экземпляра класса. Ticket.issued возвращает количество выпущенных билетов с момента последнего сброса, а Ticket.reset устанавливает счётчик обратно в 0. to_s возвращает #3 Concert.

Предоставленный код считывает строки. reset сбрасывает счётчик; любая другая строка является названием события, для которого он создаёт билет и выводит его. В конце он выводит issued: 2.

Ваш код должен находиться в ticket.rb. В main.rb содержится предоставленный код ввода/вывода, и его нельзя редактировать.

Попробуйте сами

require_relative 'ticket'

# Предоставленный код ввода/вывода: оставьте его как есть
input = []
while (line = gets)
  input << line.chomp
end
input.each do |line|
  if line == "reset"
    Ticket.reset
  else
    puts Ticket.new(line)
  end
end
puts "issued: #{Ticket.issued}"
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование

Потренируйтесь самостоятельно: Онлайн-компилятор Ruby