ruby 按定义捕获 类
ruby catch classes as they are defined
在 Ruby Gosu 中构建拼图游戏或模拟总是让我最终得到一个所有可用拼图的列表,由它们 class 保存。例如[Pipe, PipeJunktion, Box, Pump]
等。每个 class 都在几个单独的文件之一中定义,这是我从主程序中需要的。现在,每次我向游戏中添加新板块时,我都必须将 class 自己添加到此列表中。我想知道是否有办法从文件中捕获所有加载 classes。
大致如下:
allTiles = []
require_relative 'tiles.rb'.each_class {|class| allTiles << class}
会很方便。
或者这可以通过某种方式用模块解决吗?
你可以这样做:
Dir['tiles/*.rb'].each { |file| require file }
什么会收集 tiles
子文件夹中的所有文件并需要它。
下一步按文件名加载所有 类:
all_tiles = Dir['tiles/*.rb'].map do |file|
file_name = File.basename(x, '.*')
camel_cased_name = file_name.split('_').collect(&:capitalize).join
Object.const_get(camel_cased_name)
end
顺便说一下,在 Rails 中也可以这样做:
all_tiles = Dir['tiles/*.rb'].map do |file|
File.basename(x, '.*').camelize.constantize
end
检查文件添加了哪些 classes 不是一件容易或通常完成的事情。更好的方法是将所有 tile classes 放在一个命名空间下。由于可以重新打开 classes,因此可以将它们拆分为多个文件。
class Tiles
class Pipe
# ...
end
end
class Tiles
class Box
# ...
end
end
然后 Tiles.constants
可以 return 一个符号数组:[:Pipe, :Box]
,并且可以使用 Tiles.constants.map { |const| Tiles.const_get const }
获取 class 个引用列表或 Tiles.constants.map &Tiles.method(:const_get)
如果出于某种原因了解特定文件添加了哪些常量真的很重要,则以下代码显示了一种方法:
constants1 = Object.constants
require "./tiles.rb"
constants2 = Object.constants
added_constants = constants2 - constants1
如果 tiles.rb
对 Pipe
和 Box
有 class 定义,那么 added_constants
将是 [:Pipe, :Box]
。
这种方法的问题是可能会显示由 gems 添加的常量,例如:
constants1 = Object.constants
require 'mechanize'
class Foo
end
constants2 = Object.constants
added_constants = constants2 - constants1
自从我调用了 require 'mechanize'
之后,added_constants
列表将会很长并且包含的不仅仅是 Foo
。
我怀疑下面的方法有陷阱,但我会把它放出来并征求意见。
首先,使用 ObjectSpace::each_object 编译在创建任何自定义 类 之前存在的所有 类 的列表:
base_classes = ObjectSpace.each_object(Class).to_a
对于我的 Ruby (2.4.0) 版本,在 IRB 中,base_classes.size #=> 490
。现在用 require
等加载代码。假设导致创建三个 类:
class A; end
class B; end
class C; end
现在编译所有现在存在的 类 的列表并减去 base_classes
:
ObjectSpace.each_object(Class).to_a - base_classes
#=> [A, B, C]
这个 returns 由我的代码添加的 类 数组。
当然这不会显示 base_classes
中被我的代码覆盖的 类 或显示哪些 类 由所需的宝石定义。
在 Ruby Gosu 中构建拼图游戏或模拟总是让我最终得到一个所有可用拼图的列表,由它们 class 保存。例如[Pipe, PipeJunktion, Box, Pump]
等。每个 class 都在几个单独的文件之一中定义,这是我从主程序中需要的。现在,每次我向游戏中添加新板块时,我都必须将 class 自己添加到此列表中。我想知道是否有办法从文件中捕获所有加载 classes。
大致如下:
allTiles = []
require_relative 'tiles.rb'.each_class {|class| allTiles << class}
会很方便。 或者这可以通过某种方式用模块解决吗?
你可以这样做:
Dir['tiles/*.rb'].each { |file| require file }
什么会收集 tiles
子文件夹中的所有文件并需要它。
下一步按文件名加载所有 类:
all_tiles = Dir['tiles/*.rb'].map do |file|
file_name = File.basename(x, '.*')
camel_cased_name = file_name.split('_').collect(&:capitalize).join
Object.const_get(camel_cased_name)
end
顺便说一下,在 Rails 中也可以这样做:
all_tiles = Dir['tiles/*.rb'].map do |file|
File.basename(x, '.*').camelize.constantize
end
检查文件添加了哪些 classes 不是一件容易或通常完成的事情。更好的方法是将所有 tile classes 放在一个命名空间下。由于可以重新打开 classes,因此可以将它们拆分为多个文件。
class Tiles
class Pipe
# ...
end
end
class Tiles
class Box
# ...
end
end
然后 Tiles.constants
可以 return 一个符号数组:[:Pipe, :Box]
,并且可以使用 Tiles.constants.map { |const| Tiles.const_get const }
获取 class 个引用列表或 Tiles.constants.map &Tiles.method(:const_get)
如果出于某种原因了解特定文件添加了哪些常量真的很重要,则以下代码显示了一种方法:
constants1 = Object.constants
require "./tiles.rb"
constants2 = Object.constants
added_constants = constants2 - constants1
如果 tiles.rb
对 Pipe
和 Box
有 class 定义,那么 added_constants
将是 [:Pipe, :Box]
。
这种方法的问题是可能会显示由 gems 添加的常量,例如:
constants1 = Object.constants
require 'mechanize'
class Foo
end
constants2 = Object.constants
added_constants = constants2 - constants1
自从我调用了 require 'mechanize'
之后,added_constants
列表将会很长并且包含的不仅仅是 Foo
。
我怀疑下面的方法有陷阱,但我会把它放出来并征求意见。
首先,使用 ObjectSpace::each_object 编译在创建任何自定义 类 之前存在的所有 类 的列表:
base_classes = ObjectSpace.each_object(Class).to_a
对于我的 Ruby (2.4.0) 版本,在 IRB 中,base_classes.size #=> 490
。现在用 require
等加载代码。假设导致创建三个 类:
class A; end
class B; end
class C; end
现在编译所有现在存在的 类 的列表并减去 base_classes
:
ObjectSpace.each_object(Class).to_a - base_classes
#=> [A, B, C]
这个 returns 由我的代码添加的 类 数组。
当然这不会显示 base_classes
中被我的代码覆盖的 类 或显示哪些 类 由所需的宝石定义。