ruby - 需要帮助来理解这段代码

标签 ruby metaprogramming

我正在查看某人的代码,发现他已经用这样的东西完成了类评估

self.class_eval("@default_robot_engine = RobotEngine.new(some_block)")

以后是这样访问的

self.class_eval("@default_robot_engine")

我需要帮助才能理解这段代码。除了对其执行 class_eval 之外,还有其他方法可以访问 @default_robot_engine 吗?

当我执行 Class.instance_variable_names 时,我得到了

["@attribute_methods_mutex", "@generated_attribute_methods", “@generated_feature_methods”, "@observer_instances", “@每页”, “@ parent 名字”, “@registered_robot_engines”, “@default_robot_engine”, “@首要的关键”, “@quoted_primary_key”, "@locking_column", "@attribute_methods_generated", "@表名", "@quoted_table_name", "@arel_table", “@arel_engine”, “@关系”, “@列”, "@column_names", “@columns_hash”, "@cached_attributes", “@attribute_method_matchers_cache”, “@generated_external_attribute_methods”]

并且我能够像这样访问所有实例变量 ClassName.registered_robot_engine 除了 default_robot_engine。为什么?

好的,我得到了答案,因为这个实例变量是一个动态变量,并且没有在其上设置 attr_reader,所以我认为访问它的唯一方法是通过 class_eval

最佳答案

这是一段特别奇怪的代码。首先,self.class_eval 根本不是必需的。普通的 class_eval 就可以了。我猜程序员更多地使用其他语言而不是 Ruby。在 Ruby 中,只有在极少数情况下才使用显式 self 接收器,例如调用以 = 符号结尾的方法时,或者确保调用的方法是公共(public)方法时(当使用显式接收器调用时,私有(private)方法将失败。

其次,很难想象为什么程序员不使用标准的 getter 和 setter,如:

class << self
  attr_accessor :default_robot_engine
end

# Here is the case when its legal to use explicit self receiver:
self.default_robot_engine = RobotEngine.new( some_block )

然后通过以下方式轻松访问它

default_robot_engine

我强烈怀疑原始程序员对 Ruby 基础知识的无知。尽管有时有人有理由在不定义访问器的情况下篡改实例变量,但最好不要通过 class_eval,而是通过使用 #instance_variable_get/set 方法来实现:

instance_variable_set :@default_robot_engine, RobotEngine.new( some_block )
instance_variable_get :@default_robot_engine

在我看来,类 eval 对于这种情况来说太重了。

关于ruby - 需要帮助来理解这段代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18119046/

相关文章:

Ruby - 词法范围与继承

ios - 仅 TableView 第一行的自定义样式

mysql - Rails 中列名称的别名属性

c++ - 检测习语 : why does the condition have to be a `using` directive?

c# - 如何编写 C# 代码来拦截对构造函数的调用?可能是自定义预处理器或 Roslyn

mysql - 我似乎无法让 rails server 运行

ruby - 在 Ruby Regex 中使用超过 9 个未命名的捕获

ruby - 为什么我的 Ruby 代码中出现 "wrong number of arguments (0 for 2)"异常?

clojure - 如何以编程方式生成记录定义?

c++ - 使用元数据/继承来提取跨多个类的代码