I'm trying to use Ruby classes that are never instantiated, but still have the concept of inheritance.So looking at the code below, I have class "Room" that allows access to variables without instantiating the class (I have them as instance variables, but I'm not sure that's correct).
But I want to be able to further constrain the "Room" class into different types of room. And then I want each subclass to have its own variables (@log, @occpants). How would I do this?
If I use class variables, they would be overwritten for each class each time one was changed.
class Room
@log = []
@occupants = []
def self.occupants
@occupants
end
def self.log
@log
end
def self.log_entry(person)
if @occupants << person
@log << "#{person.name} entered Office: #{Time.now}"
end
end
def self.log_exit(person)
if @occupants.delete(person)
@log << "#{person.name} exited Office: #{Time.now}"
end
end
end
class Office < Room
end
class Kitchen < Room
end
From what I have understood, you are actually trying to create an Abstract class that will hold the implementations of few common attributes and behaviors of different types of Rooms. Yes, I mentioned it as Abstract instead of Singleton because you want to use Room without instantiating it, but in the case of Singleton there will be exactly one instance of Room.
And by declaring variables inside the class level scope, like this :
class Room
@log = []
@occupants = []
...
end
You are setting up 'class instance variables' rather than 'class variables' (the ones that has the '@@' prefix). Class instance variables are unique to that class, and they will not get inherited when sub-classed.
But using class variables also will not work in this case, because each room should have its own set of occupants and logs. If you use class variables the parent class and all its sub-classes will have the same common class variables.
I recommend implementing the common stuffs as instance methods and use instance variables instead.
class Room
def initialize
@log = []
@occupants = []
end
def occupants
@occupants
end
def log
@log
end
def log_entry(person)
if @occupants << person
@log << "#{person.name} entered Office: #{Time.now}"
end
end
def log_exit(person)
if @occupants.delete(person)
@log << "#{person.name} exited Office: #{Time.now}"
end
end
end
class Office < Room
end
class Kitchen < Room
end
EDIT : Btw, you should replace the 'Office' in the entered and exited messages of the logs with #{self.class}.