2016-09-25 50 views
3

我有以下类:如何在Ruby中重写Array构造函数?

class Library < Array 
    attr_accessor :authors 
end 

而且我想,用来初始化的作者之类的构造函数中的属性,并且仍然使用Array#新的行为。我试过这个:

class Library < Array 
    attr_accessor :authors 

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

end 

但是这会产生一个错误。

我该如何做到这一点?

+0

一种方法是将'Array :: new'别名为'Array :: old_new',然后创建一个新的'Array :: new'方法,根据需要做你想做的事情或做什么。调用'Array :: old_new'。 –

回答

2

因此,#initialize覆盖失败,因为您使用的是对象图示(**)而不是阵列图示(*)。

但是你不应该这样做。对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 
+0

如果你从'Array'继承,那你为什么必须包含'Enumerable'? –

+2

@ jack-noble可能意味着从类定义中删除'。感谢关于不继承Array的警告,这是一个很好的地雷! – gmcnaughton

+0

@gmcnaughton是的,我打算删除子类。对不起,编辑。 –