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]