ruby中的元/动态/泛型编程

ruby中的元/动态/泛型编程,ruby,dynamic,metaprogramming,Ruby,Dynamic,Metaprogramming,我正在尝试创建一个通用方法: 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?(me

我正在尝试创建一个通用方法:

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是类的名称


另外,我还需要一个关于元编程和动态/泛型编程的完整教程。

我不确定您在示例中试图做什么。一般来说,在Ruby中,不检查类型。它是动态类型化的,原因是:您可以编写适用于恰好支持代码对其调用的方法的任何对象的代码

从您的评论中我可以看出,您希望扩展类
数组
,因此,当您在数组(如
an_Array.pack
)上调用方法时,将搜索数组以查找
pack
的实例并返回。Ruby有一个方法,只要发现一个方法不存在,就调用它,称为
Module\method\u missing
。例如,如果我随机决定调用
4.to_dragon(magic:4,height:700)
,Ruby解释器将尝试将
to_dragon
作为在
Fixnum
(数字类型)继承链中的某个类或模块上定义的公共方法。如果您没有对该链执行任何奇怪的操作,我们将调用对象
4
上的
method\u missing
,并使用以下参数:
[:to_dragon,{magic:4,height:700}]
。基本上,这是附加到参数前面的名称,应该给出一个块

使用此技术,您可以覆盖
方法\u 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\u missing
,以检查每个元素,查看类名是否与给定的类名匹配。如果找到一个,则返回它。否则(我们使用Ruby奇特的
|
运算符执行此操作),该函数返回的值为
nil
,并返回
|
的第二个操作数。这恰好是
method\u missing
(我们通过
super
关键字获得)的默认实现,并返回调用应得的错误

唯一的潜在问题是,如果元素的类名与数组中已经定义的方法名相同,那么这些元素将被调用,而不是使用这种特殊技术。例如,调用
一个数组。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

如果这个答案不包括一个解决方案,它至少应该引导你更接近

从你的例子中,我不确定你想做什么。一般来说,在Ruby中,不检查类型。它是动态类型化的,原因是:您可以编写适用于恰好支持代码对其调用的方法的任何对象的代码

从您的评论中我可以看出,您希望扩展类
数组
,因此,当您在数组(如
an_Array.pack
)上调用方法时,将搜索数组以查找
pack
的实例并返回。Ruby有一个方法,只要发现一个方法不存在,就调用它,称为
Module\method\u missing
。例如,如果我随机决定调用
4.to_dragon(magic:4,height:700)
,Ruby解释器将尝试将
to_dragon
作为在
Fixnum
(数字类型)继承链中的某个类或模块上定义的公共方法。如果您没有对该链执行任何奇怪的操作,我们将调用对象
4
上的
method\u missing
,并使用以下参数:
[:to_dragon,{magic:4,height:700}]
。基本上,这是附加到参数前面的名称,应该给出一个块

使用此技术,您可以覆盖
方法\u 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\u missing
,以检查每个元素,查看类名是否与给定的类名匹配。如果找到一个,则返回它。否则(我们使用Ruby奇特的
|
运算符执行此操作),该函数返回的值为
nil
,并返回
|
的第二个操作数。这恰好是
method\u missing
(我们通过
super
关键字获得)的默认实现,并返回调用应得的错误

唯一的潜在问题是,如果元素的类名与数组中已经定义的方法名相同,那么这些元素将被调用,而不是使用这种特殊技术。例如,调用
一个数组。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

如果这个答案不包括一个解决方案,它至少应该引导你更接近

对于元编程,请尝试对于元编程,请尝试方法的名称是类的名称。例如,我将一个包和一个产品保存在一个数组中,所以我使用array.pack或array.product,我可以询问参数对象是否为_a?(类),但我想创建一个接受任何内容的通用方法。如果我的评论让人困惑,请回答我。有一种有趣的方法可以通过元编程实现这一点,我现在将添加它。方法的名称是类的名称。示例我将一个包和一个产品保存在一个数组中,所以我使用array.pack或array.product,我可以询问参数ob