Ruby IRB 中的对象区分大小写

Ruby Object Case-Sensitive in IRB

所以我 运行 陷入了一个关于 object/receiver 个案例 (upper/lower) 的有趣困境。惯例规定小写,但似乎出了点问题。 但是,就我而言,我的代码仅在实例以上限开头时才有效?快把我逼疯了!

我正在使用带有 Ruby 的启动命令提示符。 IRB 2.3,还有 C9(问题也存在于 IDE)

一个例子:

#rex.rb
class Dog
    def wants(something)
        puts "Rex wants to #{something}."
    end
end

#rex instance is lowercase, per convention and the book's fidelity
rex = Dog.new
rex.wants("play")

这个 运行s 在我的机器上(通过 ruby rex.rb)和 irb(通过 require "rex")也是如此。它 运行s。 但是,然后在irb中:

rex.wants("x") yields a NameError basically saying rex object is undefined.

为了解决这个问题,我必须修改代码:

#rex.rb
class Dog
    def wants(something)
        puts "Rex wants to #{something}."
    end
end

#Rex starts with an uppercase R now, not lowercase r - which it should be
Rex = Dog.new
Rex.wants("play")

我 运行 在我的机器上(ruby rex.rb)和 irb(需要 "rex")也是如此。 然后,在 irb 中,

Rex.wants("x") 

它 运行s (=> nil) 完美。

我的问题:为什么我必须将 object/receiver 的(第一个字母)大写? 惯例是它们以小写字母开头。

也许我正在使用的书 (Head First Into Rudy) 稍后会解决这个问题? IDK...这本书还没有触及 IRB。我只是想试验一下。希望其他受益的人...google 今天没有真正帮助我 ;(。

代码运行s...但是实例应该是小写的,不是吗?我在这里错过了什么?

有没有可能是我的机器坏了。当其他人测试它时,该代码片段在 ideone 上工作。但是它在我的机器和 c9 上对我来说失败了吗?我很茫然....

这里的问题是包含文件中定义的任何局部变量都将超出 IRB 的范围。通过定义常量,您可以解决这个问题。声明显式全局变量 $rex 或实例变量 @rex 是备选方案:

@rex = Dog.new
@rex.wants("play")

@rex 现在可以通过 IRB 访问...

@rex.wants "x"
# Rex wants to x.
# => nil 

@John Hyland 对 declaring a constant within a module 提出了建议,您也可以考虑一下。


全局使用实例变量

@mudasobwa 对全局使用实例变量的异端指责并非没有道理。在 class 的上下文之外声明 @rex 并将包含的文件导入 IRB 会将那个实例变量添加到主对象。这违反了面向对象的设计原则,可能会造成混淆,一般应避免使用全局变量。

也就是说,如果出于实验目的将其视为 "fish out of water",则全局范围的实例变量可能是合适的。我更喜欢它而不是声明一个我们打算改变的常量。实例变量也可能更类似于您最终将部署的代码;通常在 railssinatra 应用程序中,实例变量在 view 可以访问的路由处理程序(例如 #get)的范围内声明。


关于实例变量

传统上,实例变量应该属于它们所在的class。这是它的样子:

# dog.rb
class Dog             
  @@population = 0    # class variable (shared across all Dogs)

  def initialize legs=4
     @legs = legs       # instance variable (for each Dog)
     @@population += 1
  end
  def amputate
    @legs-=1 if @legs > 0
    @legs
  end

  # setters and getters (we could DRY this up with attr_accessor...)
  def legs= x
    @legs = x
  end
  def legs
    @legs
  end
  def self.count
    @@population
  end
end

我们的 class 描述了狗在我们程序中的样子的 模型 。我们创建的每只狗都有自己的 实例变量 @legs 并共享一个 class 变量 @@population所有的狗。调用 Dog.new 将调用 #initialize,它默认将 @legs 设置为 4,并将总人口增加 1。从 irb,我们可以测试一下:

# irb terminal
rex = Dog.new.amputate
fido = Dog.new
puts "rex has %i legs, fido has %i legs" % [rex.legs, fido.legs]
# => rex has 3 legs, fido has 4 legs
puts "We have %i total dog(s)" % Dog.count
# => We have 2 total dog(s)