我不确定你想要从你的例子中做什么。作为一般规则,在Ruby中,您不检查类型。它是动态类型的原因:您可以编写适用于任何碰巧支持您的代码调用方法的对象的代码。
从我可以从你的意见告诉,你想扩展类Array
所以,当你调用像an_array.pack
阵列上的方法,该阵列中搜索的Pack
一个实例并返回。 Ruby有一种方法,只要发现方法不存在,称为Module#method_missing
。例如,如果我随机决定调用4.to_dragon(magic: 4, height: 700)
,则Ruby解释器将尝试将to_dragon
作为在Fixnum
(数字类型)继承链中某些类或模块上定义的公共方法。假设您没有对链条做过任何奇怪的事情,我们会通过以下参数调用method_missing
对象4
:[:to_dragon, { magic: 4, height: 700 }]
。基本上,这是名称附加到参数的前面,应该给出一个块。
使用这种技术,你可以覆盖method_missing
得到这个代码的解决方案:
class String
def method_to_class
split('_').map(&:capitalize).join
end
end
class Array
def method_missing(method_name, *arguments, &block)
find do |element|
element.class.name == method_name.to_s.method_to_class
end || super
end
end
您添加一个方法来String
的方法名转换为一个类名。然后,您在Array
上重新定义method_missing
以检查每个元素,以查看类名是否与给定类名匹配。如果找到了,那么返回。否则(我们使用Ruby的花式||
运算符执行此操作),则从该函数返回的值为nil
,并返回||
的第二个操作数。这恰好是method_missing
(我们通过super
关键字获得)的默认实现,并返回该呼叫应得的错误。
唯一的潜在问题是,如果您的元素名称与已经在数组中定义的方法名称相同,那么将调用这些元素,而不是使用此特殊技术。例如,调用an_array.hash
将为您提供数组的散列码,而不是散列的第一个实例。
在这方面更安全的技术更类似于我认为你想要做的事情。实际上它使用类对象,你可以用它来覆盖其他方法:
class Array
def add(class_object)
class << self
define_method class_object.name do
find do |element|
element.is_a? class_object
end
end
end
end
end
这直接对数组的一个实例定义了新的方法。例如:
an_array = [Array, Hash, Dragon].map &:new
an_array.add Hash
an_array.hash #=> {}
如果此答案不包括解决方案,它应该至少引导您更接近!
来源
2011-03-24 02:03:13
Tom
对于元编程尝试http://pragprog.com/titles/ppmetr/metaprogramming-ruby – blu 2011-03-23 16:12:05
感谢您的帮助 – maxiperez 2011-03-23 17:41:19