Ruby 在我的数组子类中重写“each”和“[]”,这是可行的,但“select”似乎忽略了它

Ruby 在我的数组子类中重写“each”和“[]”,这是可行的,但“select”似乎忽略了它,ruby,select,each,Ruby,Select,Each,我有一个类,希望“每个”生成另一个自定义对象,所以我写了以下内容: class Fq_price_set < Array ... def [](i) # instead of returning an array, it returns an Fq_price_rec based on the array at i Fq_price_rec.new(super(i)) end def each c = 0 until c == size

我有一个类,希望“每个”生成另一个自定义对象,所以我写了以下内容:

class Fq_price_set < Array
 ...
  def [](i)
    # instead of returning an array, it returns an Fq_price_rec based on the array at i
    Fq_price_rec.new(super(i))
  end  

  def each
    c = 0
    until c == size
      yield self.[](c)
      c += 1
    end
  end
...
end
它显示Fq\u价格\u建议。类似地

my_price_set.each {|rec| puts rec.mymethod}
为该方法调用输出正确的值

但当我使用select时,例如

my_price_set.select {|rec| rec.mymethod == 1}
我得到一个错误消息,数组的未定义方法“mymethod”:。。。因此,“select”中的rec不是Fq_price_rec,而是Fq_price_rec是其子类的数组。我显然错误地认为重写'each'意味着像'select'这样的迭代方法将使用它,即'each'的子类版本。这是一个简单的答案,我也必须覆盖“选择”,还是有一个更优雅的解决方案

是的,我是Ruby的新手


TIA

为什么不放弃从数组继承,而只使用include Enumerable


像那样对数组进行子类化并不是很好。原因是C语言中的Ruby解释器内部实现了大量数组;数组实现对数组的行为做了一定的假设,以避免从C实现到Ruby land再回到C的额外往返成本

特别是,以下内容如下所示:

static VALUE
rb_ary_select(VALUE ary)
{
    VALUE result;
    long i;

    RETURN_ENUMERATOR(ary, 0, 0);
    result = rb_ary_new2(RARRAY_LEN(ary));
    for (i = 0; i < RARRAY_LEN(ary); i++) {
        if (RTEST(rb_yield(RARRAY_PTR(ary)[i]))) {
            rb_ary_push(result, rb_ary_elt(ary, i));
        }
    }
    return result;
}
Ruby直接访问内部C数组,而无需使用[]运算符

所以你应该听格林先生说:

包括可枚举的。 添加您需要的任何额外方法和运算符,以便像数组一样嘎嘎作响。
class Fq_price_set
  include Enumerable

  def initialize(actual_array)
    @actual_array = actual_array
  end

  # Make [] and each refer to values from @actual_array
end
static VALUE
rb_ary_select(VALUE ary)
{
    VALUE result;
    long i;

    RETURN_ENUMERATOR(ary, 0, 0);
    result = rb_ary_new2(RARRAY_LEN(ary));
    for (i = 0; i < RARRAY_LEN(ary); i++) {
        if (RTEST(rb_yield(RARRAY_PTR(ary)[i]))) {
            rb_ary_push(result, rb_ary_elt(ary, i));
        }
    }
    return result;
}
RARRAY_PTR(ary)[i]