有没有require
的版本在 ruby 中,要么加载整个文件,要么什么也不加载?
问题是 require 从顶部开始加载,如果它遇到问题,最终会得到未完成的定义,例如,以下内容仍然会加载 class A
即使module C
未定义:
class B
include C
end
在我的特定情况下,我有大量相互依赖的文件,以及加载这些文件的加载器。为了举例说明,我将把文件集简单地分为 4 个文件(a.rb、b.rb、c.rb 和 w.rb)。以下是这些文件的列表:
# In file a.rb
class A
@foo = []
@foo.push("in A")
def self.inherited(subclass)
foo = @foo.dup
subclass.instance_eval do
@foo = foo
end
end
def self.get_foo
@foo
end
end
# In file b.rb
class B < A
include C # if C is not already defined, the following line will not get executed although B will be defined.
@foo.push("in B")
end
# In file c.rb
module C
end
# In file w.rb
class W < B
@foo.push("in W")
end
加载器的工作方式是获取当前文件的列表,并尝试逐一要求它们。如果任何文件失败,它将保留在列表中并稍后重试。代码是这样的:(为了简单起见,删除了很多细节)
# In file loader.rb
files = Dir["*.rb"].reject { |f| f =~ /loader/ }
files.sort! # just for the purpose of the example, to make them load in an order that causes the problem
files.reject! { |f| require(f) rescue nil } while files.size > 0
我最终希望它加载A,然后发现B不能单独加载(所以跳过它),然后加载C,然后发现W还不能加载(所以跳过它),然后返回先B,然后W。
在这种情况下,输出 p W.get_foo
将是["in A", "in B", "in W"]
,这就是我想要的。
实际发生的情况是,它加载A,然后部分加载B,然后C,然后当谈到W时,它相信它可以加载它(因为B已经定义了)。这会触发self.inherited
在错误的时间编写代码,并复制尚未就绪的值 @foo
,给出输出 p W.get_foo
错误地为 ["in A", "in W"]
.
要么全有,要么全无 require
就可以解决了。
有什么想法吗?
最佳答案
如果一个文件依赖于另一个文件,则该文件本身应该需要依赖关系。例如,b.rb
应如下所示:
require 'a'
require 'c'
class B < A
include C # if C is not already defined, the following line will not get executed although B will be defined.
@foo.push("in B")
end
和w.rb
应如下所示:
require 'b'
class W < B
@foo.push("in W")
end
此后,外部加载顺序不再重要,也不需要“全有或全无”的方法。当 b
加载时,它首先会看到 a
的 require 并意识到它已经被加载,然后它会 require c
因为它意识到了它尚未加载。当再次需要c时,它将从外循环中跳过。
注意:请小心您的 $LOAD_PATH 和传递给 require
的路径。当路径相同时,Ruby 仅识别重复的需求。最好使用相对路径(相对于$LOAD_PATH中的路径)而不是绝对路径;否则,一个文件可能会被加载两次。
关于ruby - Ruby 需要全有或全无吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1113532/