超越“每个”;和“[]”在我的数组子类中,它可以工作,但是“选择”;似乎忽略了它

发布于 2024-11-15 22:16:27 字数 889 浏览 0 评论 0原文

我有一个类,我希望“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
      yield self.[](c)
      c += 1
    end
  end
...
end

这有效:当我这样做时

my_price_set.each {|rec| puts rec.class}

,它会显示 Fq_price_rec。同样,

my_price_set.each {|rec| puts rec.mymethod}

输出该方法调用的正确值。

但是当我使用 select 时,例如,

my_price_set.select {|rec| rec.mymethod == 1}

我收到错误消息,“未定义的方法”'mymethod' for Array:... 因此,rec(在'select'中)不是 Fq_price_rec,它是一个数组(Fq_price_rec 是其中的子类) )。我(显然是错误的)认为重写“each”意味着像“select”这样的迭代方法会使用它,即子类的“each”版本。简单的答案是我还必须覆盖“选择”,或者是否有更优雅的解决方案。

是的,我对 Ruby 还很陌生。

TIA

I have a class where I want 'each' to yield another custom object, so I wrote this:

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

This works: when I do

my_price_set.each {|rec| puts rec.class}

it shows Fq_price_rec. Similarly,

my_price_set.each {|rec| puts rec.mymethod}

outputs the proper value for that method call.

But when I use select, e.g.,

my_price_set.select {|rec| rec.mymethod == 1}

I get an error msg, "undefined method" 'mymethod' for Array:... So rec (in 'select') is not an Fq_price_rec, it's an array (of which Fq_price_rec is a subclass). I (obviously mistakenly) thought that overriding 'each' would mean that the iterating methods like 'select' would use it, i.e., the subclass's version of 'each'. Is the simple answer that I must also override 'select', or is there a more elegant solution.

Yes, I'm pretty new at Ruby.

TIA

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

踏月而来 2024-11-22 22:16:27

为什么不摆脱从 Array 继承,而只使用 include Enumerable 呢?

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

Why not get rid of inheriting from Array, and just have include Enumerable?

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
倾`听者〃 2024-11-22 22:16:27

像这样子类化 Array 效果不太好。原因是很多Array是在Ruby解释器内部用C实现的; Array 实现对 Array 的行为方式做出了某些假设,以避免从 C 实现到 Ruby 领域再返回到 C 的额外往返成本。

特别是 select 的实现如下所示:

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]

Ruby 直接访问内部C 数组,无需查看您的版本[] 运算符。

所以你应该听格林先生的话:

  • 包括可枚举的。
  • 添加您需要像数组一样嘎嘎叫的任何额外方法和运算符。

Subclassing Array like that doesn't work very well. The reason is that a lot of Array is implemented inside the Ruby interpreter in C; the Array implementation makes certain assumptions about how Array behaves in order to avoid the cost of an extra round trip from the C implementation, into Ruby-land, and back down to C.

In particular, the implementation of select looks like this:

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;
}

The part that is giving you grief is this:

RARRAY_PTR(ary)[i]

Ruby is directly accessing the internal C array without going through your version of the [] operator.

So you should listen to Mr. Grimm:

  • Include Enumerable.
  • Add any extra methods and operators that you need to quack like an Array.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文