Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby class instance variables and inheritance

I have a Ruby class called LibraryItem. I want to associate with every instance of this class an array of attributes. This array is long and looks something like

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

Note that these attributes are not really supposed to be methods, just a list of attributes that a LibraryItem has.

Next, I want to make a subclass of LibraryItem called LibraryBook that has an array of attributes that includes all the attributes of LibraryItem but will also include many more.

Eventually I will want several subclasses of LibraryItem each with their own version of the array @attributes but each adding on to LibraryItem's @attributes (e.g., LibraryBook, LibraryDVD, LibraryMap, etc.).

So, here is my attempt:

class LibraryItem < Object
  class << self; attr_accessor :attributes; end
  @attributes = ['title', 'authors', 'location',]
end

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

This does not work. I get the error

undefined method `push' for nil:NilClass

If it were to work, I would want something like this

puts LibraryItem.attributes 
puts LibraryBook.attributes

to output

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

(Added 02-May-2010) One solution to this is to make @attributes a simple instance variable and then add the new attributes for LibraryBoot in the initialize method (this was suggested by demas in one of the answers).

While this would certainly work (and is, in fact, what I have been doing all along), I am not happy with this as it is sub-optimal: why should these unchanging arrays be constructed every time an object is created?

What I really want is to have class variables that can inherit from a parent class but when changed in the child class do not change in the the parent class.

like image 228
rlandster Avatar asked May 02 '10 06:05

rlandster


People also ask

Are instance variables inherited in Ruby?

Instance variables are not inherited. If a method is written in the subclass with the same name and parameters as one in the parent class, the super class' method is overwritten.

Do instance variables get inherited?

I know that instance variable are not inherited but they can be accessed in sub class. If they can be accessed in sub class then does that means that they are shared between super class and subclass or both super class and subclass have different copy.

What are instance variables in Ruby?

What's an instance variable? In the Ruby programming language, an instance variable is a type of variable which starts with an @ symbol. An instance variable is used as part of Object-Oriented Programming (OOP) to give objects their own private space to store data.

Can a Ruby module have instance variables?

Explanation: Yes, Module instance variables are present in the class when you would include them inside the class.


1 Answers

Another solution would be to use the inherited hook:

class LibraryItem < Object
  class << self
    attr_accessor :attributes
    def inherit_attributes(attrs)
      @attributes ||= []
      @attributes.concat attrs
    end

    def inherited(sublass)
      sublass.inherit_attributes(@attributes)
    end
  end
  @attributes = ['title', 'authors', 'location',]
end

class LibraryBook < LibraryItem
  @attributes.push('ISBN', 'pages')
end
like image 122
tomazy Avatar answered Oct 08 '22 21:10

tomazy