【问题标题】:How can I override Array Constructor in Ruby?如何在 Ruby 中覆盖数组构造函数?
【发布时间】:2016-09-25 21:00:00
【问题描述】:

我有以下课程:

class Library < Array
  attr_accessor :authors
end

我想在类的构造函数中初始化 authors 属性,并且仍然使用 Array#new 行为。我试过这个:

class Library < Array
  attr_accessor :authors

  def initialize(**args)
     @authors = {key1: 'val1', key2: 'val2'}
     super(args)
  end

end

但这会产生错误。

我怎样才能做到这一点?

【问题讨论】:

  • 一种方法是将Array::new 别名为Array::old_new,然后创建一个新的Array::new 方法,在调用Array::old_new 之前或之后(取决于您的需要)执行您想要的操作。跨度>

标签: ruby oop


【解决方案1】:

所以 #initialize 覆盖失败​​,因为您使用的是对象 splat (**) 而不是数组 splat (*)。

但你不应该这样做。对 Ruby 的核心类进行子类化将导致各种违反直觉的行为,因为它们有许多创建该类的新实例的方法——这些方法不会被更新以创建类的新实例。例如,Library.new.reverseLibrary.new + Library.new 都将返回新数组,而不是库。

相反,您可以通过在您的类中创建一个数组实例变量并委托给它来获得您想要的行为。您可以定义 #each 并获取所有 Ruby enumerable 方法。你也可以定义任何你想要的数组方法。

class Library
  include Enumerable
  attr_accessor :authors

  def initialize(*args)
    @authors = {key1: 'val1', key2: 'val2'}
    @array = args
  end

  def each(&block)
    @array.each(&block)
  end

  def [](index)
    @array[index]
  end
end

【讨论】:

  • 如果你是从Array 继承的,那么为什么你必须包含Enumerable
  • @jack-noble 可能意味着从类定义中删除 &lt; Array。感谢关于不继承 Array 的警告,这是一个很好的地雷!
  • @gmcnaughton 是的,我的意思是删除子类。抱歉,正在编辑。
猜你喜欢
  • 2014-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-09
  • 2018-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多