【问题标题】:Ruby Extended Array class that supports full method chain支持完整方法链的 Ruby 扩展数组类
【发布时间】:2019-11-14 19:19:46
【问题描述】:

短:

有没有一种方法可以创建扩展的Array 类,名为A,它支持带有map、sort、sort_by 和新方法word 的完整方法链,并且不会损害Array 类?

例子:

 [
    A.new(a).word,
    A.new(a).sort.word,
    A.new(a).sort_by(&:-@).word,
    A.new(a).map(&:chr).sort.map(&:ord).word
  ]

长篇大论:

我解决了这个kata 并使用新的word 方法创建了扩展Array 类的代码:

class Array
  def word
    [*self[0..1],*self[-2..-1]].map(&:chr).join
  end
end
def sort_transform(a)
  [
    a.word,
    a.sort.word,
    a.sort_by(&:-@).word,
    a.map(&:chr).sort.map(&:ord).word
  ].join ?-
end

然后我认为为这种基类添加方法不是一个好主意。我尝试实现一个新类,该类继承了 Array 的所有行为。

class A < Array
  def word
    [*self[0..1],*self[-2..-1]].map(&:chr).join
  end
end

这个添加破坏了我的代码,因为map、sort、sort_by 返回一个Array 实例:A.new([1,2,3]).sort.class # Array。并且 Array 不理解 word 方法。而不是A.new(a).sort.word,我必须将链的一部分封装到A.new构造函数中:A.new(a.sort).word。这肯定会破坏纯方法链。

是否可以扩展Array 以达到这样的纯方法链; A.new(a).sort.word?

当我试图写这行时: A类

def word
    [*self[0..1],*self[-2..-1]].map(&:chr).join
  end
  def sort
    A.new(self.sort)
  end
end

这给我带来了main.rb:8:in 'sort': stack level too deep (SystemStackError) 最后已经写了这行我找到了一种避免深栈的方法:将self转换为Array,然后再次将其转换为A。

class A < Array
  def word
    [*self[0..1],*self[-2..-1]].map(&:chr).join
  end
  def sort
    A.new(self.to_a.sort)
  end
end

那么这是实现此类扩展的唯一方法吗?

【问题讨论】:

  • 这篇文章给了我words.steveklabnik.com/beware-subclassing-ruby-core-classes 给我这篇文章的开发人员告诉我,由于C 代码,实例在Ruby 的方法链中被转换回Array。它实现了速度。
  • 我会改用Array 的改进。为什么没有人使用细化?
  • @Amadan 这就是我写这个问题的原因:) 获取您提供的信息。
  • 为什么要给Array添加实例方法,子类Array或者细化Array。为什么不为给定数组定义一个带有一个参数的方法word?
  • @CarySwoveland:你为什么不提炼?这就是为什么他们为。为什么要细化一个函数?因为它更好地链接,并且链接读取更自然,因为它线性表示因果关系。 f.each_line.map(&amp;:length).max 有流量。 find_max(get_lines(f).map(&amp;:length)) 来回走动会带来更高的精神负担。语法和执行顺序之间的非并行性是我不喜欢 Python 的原因之一:为什么 len 是一个函数,而 lower 是一个方法,而 map 是一个函数,而 join 是 string 但sorted 是一个函数,但sort 是一个方法...和推导... >.

标签: arrays ruby oop inheritance


【解决方案1】:

如果您想对核心类进行猴子补丁,但您认为它很恶心,您应该记住,这些改进是专门针对这种情况进行的。

module ArrayWithWord
  refine Array do
    def word
      [*self[0..1],*self[-2..-1]].map(&:chr).join
    end
  end
end

class WordTest
  using ArrayWithWord

  # [].word works here
  def self.sort_transform(a)
    [
      a.word,
      a.sort.word,
      a.sort_by(&:-@).word,
      a.map(&:chr).sort.map(&:ord).word
    ].join ?-
  end
end

WordTest.sort_transform(%w(foo bar baz quux))
# => "fbbq-bbfq-bbfq-bbfq"

# [].word doesn't work here
[].word
# => NoMethodError (undefined method `word' for []:Array)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-25
    • 1970-01-01
    • 2013-07-03
    相关资源
    最近更新 更多