Ruby 变量
Ruby 变量 (Variables)、常量 (Constants) 和字面量 (Literals)
Section titled “Ruby 变量 (Variables)、常量 (Constants) 和字面量 (Literals)”变量 (Variables) 是命名的内存位置,用于存储程序使用的数据。理解 Ruby 如何处理变量、常量 (Constants) 和各种数据字面量 (Literals),对于编写高效的 Ruby 代码至关重要。
Ruby 支持几种类型的变量,每种都有特定的作用域 (Scope) 和用途。本章将深入探讨这些类型,并在任何先前的简要介绍基础上进行更详细的阐述。
Ruby 全局变量 (Global Variables)
Section titled “Ruby 全局变量 (Global Variables)”全局变量以美元符号 ($) 开头。例如,$admin_user。如果在初始化之前使用了全局变量,它的值为 nil(表示“无”或未定义)。如果 Ruby 运行带有 -w 或 -W(详细模式)标志,使用未初始化的全局变量会产生警告。
给全局变量赋值后,它可以在程序中的任何地方访问。然而,通常不鼓励广泛使用全局变量。它们可能使程序难以理解、调试 (Debug) 和维护,因为它们可以在任何地方被修改,导致意想不到的副作用 (Side Effects)。优先通过方法参数 (Method Arguments) 传递数据或使用其他作用域机制。
以下是演示全局变量用法的示例:
#!/usr/bin/env ruby
$global_variable = 10
class Class1 def print_global puts "Global variable in Class1 is #{$global_variable}" endend
class Class2 def print_global puts "Global variable in Class2 is #{$global_variable}" endend
class1_obj = Class1.newclass1_obj.print_global
class2_obj = Class2.newclass2_obj.print_global在此示例中,$global_variable 在 Class1 和 Class2 中都可访问。此代码将输出:
Global variable in Class1 is 10Global variable in Class2 is 10字符串插值 (String Interpolation) 注意事项:在 Ruby 中,要在双引号字符串中嵌入变量或表达式的值,可以使用 #{expression} 语法。例如,"Value: #{my_variable}"。
Ruby 实例变量 (Instance Variables)
Section titled “Ruby 实例变量 (Instance Variables)”实例变量以 @ 符号开头,例如,@user_name。它们属于类的特定实例 (Instance)(即对象 Object)。每个对象都有自己的一组实例变量。未初始化的实例变量值为 nil,如果在赋值前访问,使用 -w 选项会产生警告。
以下是实例变量的示例:
#!/usr/bin/env ruby
class Customer def initialize(id, name, address) @cust_id = id @cust_name = name @cust_address = address end
def display_details puts "Customer ID: #{@cust_id}" puts "Customer Name: #{@cust_name}" puts "Customer Address: #{@cust_address}" endend
# 创建对象cust1 = Customer.new("1", "John Doe", "123 Main St, Anytown")cust2 = Customer.new("2", "Jane Smith", "456 Oak Ave, Otherville")
# 调用方法cust1.display_detailscust2.display_details在这里,@cust_id、@cust_name 和 @cust_address 是实例变量。每个 Customer 对象都有这些变量自己的值。输出将是:
Customer ID: 1Customer Name: John DoeCustomer Address: 123 Main St, AnytownCustomer ID: 2Customer Name: Jane SmithCustomer Address: 456 Oak Ave, OthervilleRuby 类变量 (Class Variables)
Section titled “Ruby 类变量 (Class Variables)”类变量以两个 @ 符号开头,例如,@@total_users。它们在类的所有实例以及类本身及其子类 (Subclasses) 之间共享。类变量必须在使用它们的方法定义 (Method Definitions) 之前进行初始化,否则会发生错误。如果启用了 -w 选项,在子类中重写类变量可能导致警告。
以下是类变量的示例:
#!/usr/bin/env ruby
class Customer @@no_of_customers = 0 # 初始化类变量
def initialize(id, name, address) @cust_id = id @cust_name = name @cust_address = address @@no_of_customers += 1 end
def display_details puts "Customer ID: #{@cust_id}" puts "Customer Name: #{@cust_name}" puts "Customer Address: #{@cust_address}" end
def self.total_no_of_customers # 类方法访问类变量 puts "Total number of customers: #{@@no_of_customers}" endend
# 创建对象cust1 = Customer.new("1", "John Doe", "123 Main St, Anytown")cust2 = Customer.new("2", "Jane Smith", "456 Oak Ave, Otherville")
# 调用类方法Customer.total_no_of_customers
cust3 = Customer.new("3", "Robert Brown", "789 Pine Ln, Sometown")Customer.total_no_of_customers这里,@@no_of_customers 是一个类变量。它跟踪创建的 Customer 对象的总数。输出将是:
Total number of customers: 2Total number of customers: 3Ruby 局部变量 (Local Variables)
Section titled “Ruby 局部变量 (Local Variables)”局部变量以小写字母或下划线 (_) 开头。例如,count 或 _temp。局部变量的作用域仅限于其声明所在的块 (Block)、方法 (Method)、类 (Class) 或模块 (Module) 定义。它们在其定义范围之外不可用。
如果引用未初始化的局部变量,Ruby 会将其解释为对同名方法的调用且不带参数。如果不存在这样的方法,则会引发 NameError。
按照局部变量命名约定给名称赋值,即可将其声明为局部变量。它存在直到其当前作用域结束。在上面的 Customer 类示例中,id、name 和 address(initialize 的参数)是该方法内的局部变量。
Ruby 常量 (Constants)
Section titled “Ruby 常量 (Constants)”常量以大写字母开头。例如,Version 或 MAX_USERS。在类或模块内定义的常量可以在该类或模块内部访问。在任何类或模块外部定义的常量是全局可访问的。
常量不能在方法内定义。尝试引用未初始化的常量会导致 NameError。虽然 Ruby 允许您为已初始化的常量重新赋值,但这会产生警告,因为常量的设计用途是保存不会改变的值。
#!/usr/bin/env ruby
class Example VAR1 = 100 VAR2 = 200
def show puts "Value of first Constant is #{VAR1}" puts "Value of second Constant is #{VAR2}" endend
# 创建对象object = Example.newobject.show
# 从类外部访问常量(如果在顶级或使用作用域解析运算符定义)# puts Example::VAR1 # 这是从外部需要时访问它的方式这里,VAR1 和 VAR2 是常量。输出将是:
Value of first Constant is 100Value of second Constant is 200Ruby 伪变量 (Pseudo-Variables)
Section titled “Ruby 伪变量 (Pseudo-Variables)”伪变量是特殊的关键字,行为类似于变量,但其值不能由您的代码赋值。它们具有预定义的含义。
self: 当前方法的接收对象。在类定义中但在实例方法外部,self指代类本身。true: 表示布尔真值。false: 表示布尔假值。nil: 表示 ‘无’ 或未定义的值。它是一个对象,是NilClass的唯一实例。FILE: 当前源文件的路径。LINE: 源文件中的当前行号。ENCODING: 当前文件的脚本编码。
Ruby 基本字面量 (Basic Literals)
Section titled “Ruby 基本字面量 (Basic Literals)”字面量是直接在源代码中表示的固定值。Ruby 的字面量规则通常很直观。
整数字面量 (Integer Literals)
Section titled “整数字面量 (Integer Literals)”Ruby 支持整数。自 Ruby 2.4 起,Fixnum 和 Bignum 被统一到一个单独的 Integer 类中,该类自动处理任何大小的数字,仅受可用内存限制。您不再需要担心小整数和大整数之间的区别。
整数可以带有可选的前导符号。您可以使用进制指示符:0 用于八进制(例如,0o377 或 0377),0x 用于十六进制(例如,0xff),以及 0b 用于二进制(例如,0b1011)。下划线字符 (_) 可以用于数字内部以增强可读性,并且会被忽略(例如,1_234_567)。
字符前加问号 (?) 会得到其 ASCII/编码整数值(例如,?a 是字符 ‘a’ 的整数值,?\n 是换行符的整数值)。
示例:
123 # Decimal1_234 # Decimal with underscore for readability-500 # Negative decimal0o377 # Octal (or 0377)0xff # Hexadecimal0b1011 # Binary?a # Integer code for character 'a'?\n # Integer code for newline (0x0a)12345678901234567890 # A large integer浮点数字面量 (Floating-Point Literals)
Section titled “浮点数字面量 (Floating-Point Literals)”Ruby 支持浮点数(带小数点的数字)。它们是 Float 类的对象。
示例:
123.4 # Standard floating point1.0e6 # Scientific notation (1.0 * 10^6)4E20 # Scientific notation (dot not required if 'E' is present)4e+20 # Sign for exponent is optional for positive字符串字面量 (String Literals)
Section titled “字符串字面量 (String Literals)”Ruby 字符串是字节序列,通常表示字符,并且是 String 类的对象。Ruby 支持多种创建字符串的方式:
- 单引号字符串 (
’…’): 执行最少的解释。反斜杠符号仅支持‘(表示字面单引号)和\(表示字面反斜杠)。不执行插值 (#{…})。 - 双引号字符串 (
”…”): 支持广泛的反斜杠转义序列(见下文)并使用#{expression}进行表达式插值。 %q{…}或%Q{…}(及其他分隔符): 通用字符串引用。%q的行为类似于单引号,%Q的行为类似于双引号。您可以使用各种分隔符对,如()、[]、<>,甚至非成对字符,如!…!或|…|。
单引号和双引号示例:
#!/usr/bin/env ruby
puts 'escape using \\ backslash'puts 'That\'s right'
name = "Ruby"puts "Hello, #{name}!\nThis is a new line."运行结果:
escape using \ backslashThat's rightHello, Ruby!This is a new line.字符串插值示例:
#!/usr/bin/env ruby
seconds_in_a_day = 24 * 60 * 60puts "There are #{seconds_in_a_day} seconds in a day."运行结果:
There are 86400 seconds in a day.反斜杠转义符 (Backslash Notations)(双引号字符串中常用)
Section titled “反斜杠转义符 (Backslash Notations)(双引号字符串中常用)”双引号字符串和类似上下文中支持的常见反斜杠转义序列:
| 符号 (Notation) | 表示的字符 (Character Represented) |
|---|---|
\n | 换行符 (Newline) (0x0A) |
\r | 回车符 (Carriage return) (0x0D) |
\t | 水平制表符 (Horizontal tab) (0x09) |
\f | 换页符 (Formfeed) (0x0C) |
\b | 退格符 (Backspace) (0x08) |
\a | 响铃/警报符 (Bell/Alert) (0x07) |
\e | 转义符 (Escape) (0x1B) |
\s | 空格 (Space) (0x20) |
\ | 字面反斜杠 (Literal backslash) |
‘ | 字面单引号 (Literal single quote)(在 %Q{} 中有用) |
“ | 字面双引号 (Literal double quote)(在 ”…” 中有用) |
\nnn | 八进制表示法(n 为 0-7) |
\xnn | 十六进制表示法(n 为 0-9, a-f, 或 A-F) |
\u{nnnn …} | Unicode 字符(例如,\u{41 42 43} 表示 “ABC”) |
\unnnn | Unicode 字符(恰好四个十六进制数字) |
有关 Ruby 字符串的更多详细信息,包括编码和高级方法,请参阅官方 Ruby 文档中的 String 类。
数组字面量 (Array Literals)
Section titled “数组字面量 (Array Literals)”数组字面量通过将一系列用逗号分隔的对象引用放在方括号 ([]) 之间创建。末尾的逗号将被忽略。
示例:
#!/usr/bin/env ruby
my_array = ["fred", 10, 3.14, "This is a string", "last element",]
my_array.each do |item| puts itemend
# 词数组字面量(常用于字符串数组)words = %w[this is a test]puts words.inspect # => ["this", "is", "a", "test"]运行结果 (针对 my_array 部分):
fred103.14This is a stringlast element有关数组的全面信息,请参阅 Array 类文档。
哈希字面量 (Hash Literals)
Section titled “哈希字面量 (Hash Literals)”哈希字面量(也称为关联数组或字典)通过将一系列键值对放在花括号 ({}) 之间创建。键 (Key) 和值 (Value) 可以用 =>(哈希火箭,Hash Rocket)分隔,或者如果键是符号 (Symbol),可以用冒号 : 分隔(Ruby 1.9+ 语法)。末尾的逗号将被忽略。
示例:
#!/usr/bin/env ruby
# 旧语法(仍然有效)或当键不是符号时colors_hash_rocket = { "red" => 0xf00, "green" => 0x0f0, "blue" => 0x00f }
# 现代语法(用于符号键,推荐)colors_symbols = { red: 0xf00, green: 0x0f0, blue: 0x00f }
puts "Using hash rocket syntax:"colors_hash_rocket.each do |key, value| print "#{key} is #{value}\n"end
puts "\nUsing symbol key syntax:"colors_symbols.each do |key, value| print "#{key} is #{value}\n"end运行结果:
Using hash rocket syntax:red is 3840green is 240blue is 15
Using symbol key syntax:red is 3840green is 240blue is 15有关哈希的更多详细信息,请查阅 Hash 类文档。
范围字面量 (Range Literals)
Section titled “范围字面量 (Range Literals)”范围 (Range) 表示一个具有起始值和结束值的区间。范围可以使用 s..e(包含结束值)和 s...e(不包含结束值)构建,或使用 Range.new。
当用作迭代器 (Iterator) 时,范围会按顺序产生区间内的每个值。
范围 (1..5) 包含值 1、2、3、4、5。范围 (1...5) 包含值 1、2、3、4。
示例:
#!/usr/bin/env ruby
puts "包含结束值的范围:"(10..15).each do |n| print n, ' 'endputs
puts "\n不包含结束值的范围:"(10...15).each do |n| print n, ' 'endputs运行结果:
Inclusive range:10 11 12 13 14 15
Exclusive range:10 11 12 13 14有关范围的更多信息,请参阅 Range 类文档。