0

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
5
  • Why don't you use classic singleton? Commented May 16, 2015 at 22:03
  • 1
    What's not working in your attempt? Commented May 16, 2015 at 22:16
  • Hmm your example seems to be correct and what you use here is called "class level instance variables", and they will do just what you expect. Commented May 17, 2015 at 1:14
  • The point here is class is an object too in Ruby, so your class Room is an instance of the Class class, while class Office will become another instance of Class, look here how it works. Commented May 17, 2015 at 1:55
  • Why not just create regular class instances? I don't see what you gain by moving everything up to the class level. Commented May 17, 2015 at 2:38

2 Answers 2

1

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}.

Sign up to request clarification or add additional context in comments.

Comments

0

If this is logging functionality you may be better off creating a module that you can add with extend(not include) in instantiated Room(and other) classes to provide the extra static methods.

module Logger
  def log_item(person)
    logger.debug "#{person.name} entered Office: #{Time.now}"
  end
end

class Room
  extend Logger
  @log = [] #you could use this to collect statements then log at a later time? otherwise I'm not sure why you would take this approach.
  @occupants = []

  def self.log_entry(person)
    if @occupants << person
      log_item(person)
    end
  end
end

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.