我有一个名为LibraryItem的ruby类。我想与这个类的每个实例关联一个属性数组。这个数组很长,看起来像

['title', 'authors', 'location', ...]

注意,这些属性实际上不应该是方法,而是aLibraryItem拥有的属性列表。
接下来,我想创建一个名为LibraryItemLibraryBook子类,它有一个包含LibraryItem所有属性但也包含更多属性的属性数组。
最后,我想要几个LibraryItem的子类,每个子类都有自己的数组版本,但是每个子类都添加到@attributesLibraryItem(例如,@attributesLibraryBookLibraryDVD,等等)。
所以,我的尝试是:
class LibraryItem < Object
  class << self; attr_accessor :attributes; end
  @attributes = ['title', 'authors', 'location',]
end

class LibraryBook < LibraryItem
  @attributes.push('ISBN', 'pages')
end

这不起作用。我明白错误
undefined method `push' for nil:NilClass

如果可以的话,我想要这样的东西
puts LibraryItem.attributes
puts LibraryBook.attributes

输出
['title', 'authors', 'location']
['title', 'authors', 'location', 'ISBN', 'pages']

(2010年5月2日增补)
解决方法之一是将LibraryMap设置为一个简单的实例变量,然后在@attributes方法中添加LibraryBoot的新属性(这是demas在其中一个答案中建议的)。
虽然这肯定会起作用(事实上,这也是我一直在做的事情),但我并不满意这一点,因为它是次优的:为什么每次创建对象时都要构造这些不变的数组?
我真正想要的是拥有可以从父类继承的类变量,但是在子类中更改时在父类中不会更改。

最佳答案

既然您提到属性是“固定的”和“不变的”,那么我假设您的意思是,一旦创建了对象,您就永远不会更改它们的值。在这种情况下,应该使用以下方法:

class Foo
    ATTRS = ['title', 'authors', 'location']
    def attributes
        ATTRS
    end
end

class Bar < Foo
    ATTRS = ['ISBN', 'pages']
    def attributes
        super + ATTRS
    end
end

您正在手动实现一个reader方法(而不是让attr_accessor为您创建它),该方法隐藏数组的内部名称。在子类中,只需调用祖先类的reader函数,附加与子类相关联的字段,然后将其返回给调用方。对于用户来说,这看起来像一个名为attributes的只读成员变量,它在子类中有附加值。

10-08 04:23