我有一个名为LibraryItem
的ruby类。我想与这个类的每个实例关联一个属性数组。这个数组很长,看起来像
['title', 'authors', 'location', ...]
注意,这些属性实际上不应该是方法,而是a
LibraryItem
拥有的属性列表。接下来,我想创建一个名为
LibraryItem
的LibraryBook
子类,它有一个包含LibraryItem
所有属性但也包含更多属性的属性数组。最后,我想要几个
LibraryItem
的子类,每个子类都有自己的数组版本,但是每个子类都添加到@attributes
的LibraryItem
(例如,@attributes
,LibraryBook
,LibraryDVD
,等等)。所以,我的尝试是:
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
的只读成员变量,它在子类中有附加值。