ruby 中的元/动态/泛型编程
我正在尝试创建一个通用方法:
class Foo
attr_reader
def add(object)
item = @item.find { |item| item.(#the method is calling object.class) == object if item.is_a?(object.class)}
end
end
我想创建一个通用方法,它根据参数类来比较数组的元素。
示例:
item.method1 == method1 if item.is_a?(method1.class)
其中 method1 是类的名称。
另外,我需要一个关于元编程和动态/通用编程的完整教程。
I am trying to make a generic method:
class Foo
attr_reader
def add(object)
item = @item.find { |item| item.(#the method is calling object.class) == object if item.is_a?(object.class)}
end
end
I want to create a generic method which compares the element of an array depending the parameter class.
Example:
item.method1 == method1 if item.is_a?(method1.class)
where method1 is the name of class.
Also, I need a complete tutorial about metaprogramming and dynamic/generic programming.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我不确定你想从你的例子中做什么。作为一般规则,在 Ruby 中,您不检查类型。它是动态类型的有一个原因:您可以编写适用于任何碰巧支持您的代码对其调用的方法的对象的代码。
从我从您的评论中可以看出,您想要扩展类
Array
因此,当您在像an_array.pack
这样的数组上调用方法时,会搜索该数组Pack
的实例并返回。 Ruby 有一个每当发现方法不存在时就会调用的方法,称为Module#method_missing
。例如,如果我随机决定调用4.to_dragon(magic: 4, height: 700)
,Ruby 解释器将尝试查找to_dragon
作为定义在Fixnum(数字类型)继承链中的某些类或模块。如果您没有对该链执行任何奇怪的操作,我们会使用以下参数调用对象4
上的method_missing
:[:to_dragon, { magic: 4 ,高度:700}]
。基本上,这是附加到参数前面的名称,并且应该给出一个块。使用此技术,您可以重写
method_missing
来获取此代码作为解决方案:将方法添加到
String
中,以将方法名称转换为类名称。然后,您在Array
上重新定义method_missing
以检查每个元素以查看类名是否与给定的类名匹配。如果找到,则将其返回。否则(我们使用 Ruby 奇特的||
运算符来执行此操作),从该函数返回的值为nil
,第二个操作数为||
被返回。这恰好是method_missing
的默认实现(我们通过super
关键字获得)并返回调用应有的错误。唯一的潜在问题是,如果您的元素的类名与数组上已定义的方法名相同,那么将调用这些元素而不是这种特殊技术。例如,调用
an_array.hash
将为您提供数组的哈希代码,而不是哈希的第一个实例。在这方面更安全的技术与我认为您尝试做的更相似。它实际上使用类对象,您可以使用它来重写其他方法:
这直接在数组实例上定义新方法。例如:
如果这个答案不包含解决方案,它至少应该引导您更接近!
I am unsure of what you are trying to do from your example. As a general rule, in Ruby, you don't check for types. It is dynamically typed for a reason: you can write code that works for any objects that happen to support the methods your code calls on them.
From what I can tell from your comments, you want to extend the class
Array
so, when you call a method on an array likean_array.pack
, the array is searched for an instance ofPack
and returned. Ruby has a method called whenever a method is found not to exist calledModule#method_missing
. For example, if I randomly decide to call4.to_dragon(magic: 4, height: 700)
, the Ruby interpreter will attempt to findto_dragon
as a public method defined on some class or module in theFixnum
(type of numbers) inheritance chain. Provided you have not done something strange to that chain, we get a call tomethod_missing
on the object4
with these arguments:[:to_dragon, { magic: 4, height: 700 }]
. Basically, that's the name appended to the front of the arguments, and a block should one be given.Using this technique, you can override
method_missing
to get this code as a solution:You add a method to
String
to convert a method name to a class name. Then, you redefinemethod_missing
onArray
to check each element to see if the class name matches the given class name. If one is found, then that is returned. Otherwise (and we do this using Ruby's fancy||
operator), the value returned from that function isnil
and the second operand to||
is returned. This happens to be the default implementation formethod_missing
(which we get by thesuper
keyword) and returns the error the call deserves.The only potential issue with that is, if you have elements that have class names identical to method names that are already defined on arrays, then those will be called instead rather than this special technique. For example, calling
an_array.hash
will give you the hash code of the array rather than the first instance of a hash.A safer technique in this respect is more similar to what I think you were trying to do. It actually uses class objects, and you can use it to override other methods:
This defines new methods directly on an instance of an array. For example:
If this answer does not include a solution, it should at least guide you closer!