学习Ruby常量的相关知识

168 阅读2分钟

动机

在[bootrAils]启动程序中,我们没有很多Ruby常量。然而,当需要时,知道它们是如何工作的总是好的。
"常量 "是不允许改变的变量。让我们来看看是怎样的。在这篇文章中,我们将使用ruby控制台,如果你在Rails环境中,你可以通过输入bin/rails console

如何定义一个Ruby常量

常量以大写字母开头。

例子:

Boiling = 100 # valid
BOILING = 100 # valid
boiling = 100 # invalid

定义在类或模块内的常量可以从内部直接访问。那些定义在类或模块之外的常量仍然可以被全局访问。

例子:

class Water
   ICE = 0
   BOIL = 100
   def show
      puts "Celsius temperature for becoming ice is #{ICE}"
      puts "Celsius temperature for becoming steam is #{BOIL}"
   end
end

你可以注意到,ICE和BOIL可以从定义它们的类中自由访问。从外部:

Water::ICE
# => 0
Water::BOIL
# => 100
Water.new.show
# => Celsius temperature for becoming ice is 0
# => Celsius temperature for becoming steam is 100

会失败的Ruby常量

常量不能被定义在一个方法里面。

例子:

class Water
   def show
      ICE = 0
      BOIL = 100
      puts "Celsius temperature for becoming ice is #{ICE}"
      puts "Celsius temperature for becoming steam is #{BOIL}"
   end
end
# Traceback (most recent call last):
# SyntaxError ((irb):117: dynamic constant assignment)
# ICE = 0

常量不能以小写字母开头。

class Water
   ice = 0 # ! fail ! Constant cannot start with lowercase
   boil = 100 # ! fail ! Constant cannot start with lowercase
   def show
      puts "Celsius temperature for becoming ice is #{ice}"
      puts "Celsius temperature for becoming steam is #{boil}"
   end
end

这将在调用时产生以下错误。

Water::ice
Traceback (most recent call last):
        1: from (irb):87:in `<main>'
NoMethodError (undefined method `ice' for Water:Class)

未初始化的常量错误

如果你使用Ruby-on-Rails或其他框架编程,这种错误经常发生。它通常意味着模块中的一个类或常量没有被找到。你可以很容易地在你的电脑上重新创建这个错误。

class Water
   ICE = 0
   BOIL = 100
   def show
      puts "Celsius temperature for becoming ice is #{ICE}"
      puts "Celsius temperature for becoming steam is #{BOIL}"
   end
end

然后尝试简单地访问一个不存在的常量。

irb(main):131:0> Water::ICE
0
irb(main):132:0> Water::UNEXISTING
Traceback (most recent call last):
        1: from (irb):132:in `<main>'
NameError (uninitialized constant Water::UNEXISTING)

改变...一个Ruby常量

如果你来自其他语言,这将是一件令人不安的事情:Ruby常量可以被改变而不会产生任何错误。

Water::ICE = 42
# => warning: already initialized constant Water::ICE
Water::ICE
# => 42

一个警告被提出,但程序仍然继续。

如果你想避免这种默认行为,你必须freeze 你的常量。

在这个例子中,我打算冻结......冰块。

class Water
   ICE = 0.freeze
   BOIL = 100.freeze
   def show
      puts "Celsius temperature for becoming ice is #{ICE}"
      puts "Celsius temperature for becoming steam is #{BOIL}"
   end
end

这其实并不奏效,因为你仍然可以使Water::ICE = 42 ,并且有一个简单的警告。

一个Ruby常量实际上并不是不可改变的,而且你不能冻结一个变量。