Ruby类中声明的实例变量无法被方法识别,方法内声明则正常
实例变量与类实例变量的那些坑——从Java转Ruby必看
嘿,刚从Java转Ruby确实会碰到不少变量作用域的小误区,我来帮你把这个问题掰扯清楚~
首先得明确一个Ruby和Java不一样的核心规则:
在Ruby的类体中直接定义的
@name_array,不是实例对象的实例变量,而是类的实例变量!
换句话说,这个@name_array是属于Problem022这个类本身的,而你通过Problem022.new创建出来的实例对象,有自己独立的实例变量空间,和类的实例变量完全是两回事。你的do_problem、read_input这些实例方法,是属于实例对象的,它们访问的@变量是实例对象自己的,自然就找不到类里定义的那个@name_array啦。
对比Java的话,Java里类中直接定义的变量默认是实例变量,但Ruby的规则刚好在这一点上有差异,很容易混淆。
解决方案有两种,看你的需求选:
1. 定义真正的实例对象变量(最常用)
如果每个Problem022的实例都需要自己独立的name_array,那就在实例的初始化方法里定义它:
class Problem022 FILENAME = "resources/p022_names.txt" # 初始化实例时创建实例变量 def initialize @name_array = [] end def do_problem read_input() sort_input() # 更多操作 end def read_input File.open(FILENAME, "r") do |file| file.each_line do |line| scanner = StringScanner.new(line) while scanner.exist?(/,/) do # 这里可以直接操作@name_array了,它属于当前实例 end end end end def sort_input @name_array.sort! # 后续排序逻辑 end end
2. 用类共享的变量(如果所有实例共用同一个数组)
如果这个数组是整个类共享的,不需要每个实例独立拥有,那可以把它改成类变量(用@@前缀),或者保留类实例变量并通过类方法访问:
方式A:类变量
class Problem022 FILENAME = "resources/p022_names.txt" @@name_array = [] # 类变量,所有实例共享 def do_problem read_input() sort_input() end def read_input File.open(FILENAME, "r") do |file| file.each_line do |line| scanner = StringScanner.new(line) while scanner.exist?(/,/) do @@name_array << "提取到的名字" # 直接操作类变量 end end end end def sort_input @@name_array.sort! end end
方式B:类实例变量+类方法(更Ruby风格的类共享变量写法)
class Problem022 FILENAME = "resources/p022_names.txt" @name_array = [] # 类实例变量 # 类方法,提供访问类实例变量的入口 def self.name_array @name_array end def do_problem read_input() sort_input() end def read_input File.open(FILENAME, "r") do |file| file.each_line do |line| scanner = StringScanner.new(line) while scanner.exist?(/,/) do # 通过类方法访问类实例变量 self.class.name_array << "提取到的名字" end end end end def sort_input self.class.name_array.sort! end end
最后再划个重点
Ruby里:
- 实例方法中的
@xxx→ 属于当前实例对象 - 类体中的
@xxx→ 属于类本身(类实例变量) - 类体中的
@@xxx→ 类变量,所有实例共享
从Java转过来一定要把这个差异记牢,就不会再踩这种变量找不到的坑啦~
内容的提问来源于stack exchange,提问作者SOLO
相关产品推荐
相关产品推荐

