Menu
CoddyTech

实例变量

本课属于 Coddy Ruby 学习旅程的“面向对象编程”单元。第 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

在 class << self 中使用 attr_accessor,会在类上生成读取器和设置器。之后,实例可以通过 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 在线编译器