1
votes

I have a task where I have elder class and subclasses. Here is simplified code:

 class Animal
  attr_accessor :name, :name_list

  def initialize
    @name = name
    @name_list = []

  end
  
  def set_name
    @name = gets
    puts "My name is #{@name}"
    @name_list.append(@name)
  end

  def self.show_all
    puts "List of your animals names: #{@name_list}"
  end
end

class Dog < Animal

end

class Cat < Animal

end


dog1 = Dog.new
dog1.set_name
cat1 = Cat.new
cat1.set_name
Animal.show_all

So the question is: if all of the subclasses (cat and dog) have the same element - name(which is places in Animal class), how can I collect all of them in one array? Because if I just put name_list in set_name def - array appears to be empty. Is there any way to make it without writing another array outside the classes?

1
Yes, it is is possible, BUT, you're almost certainly doing it wrong. A class should not normally have any knowledge of its instances, nor its subclasses, nor the instances of those subclasses. This is a violation of data encapsulation, which is a fundamental principle in object oriented programming. - Tom Lord
If you need to have some encapsulated knowledge of "all the animals", then you would probably be advised to define this in a separate object, for example, pets = [dog1, cat1] and pet_names = pets.map(&:name). - Tom Lord
I see, thank you for advice. Encapsulation is the hardest part of OOP for me personally. I just got a task to collect all elements from a subclasses and it's more comfortable for me if I, for example, have a lot of class objects (not only cat/dog/lion but much more) and I am not allowed to use Data Bases. - Silka
If this is an academic question specifically about using class variables, then fair enough. But there are all sorts of ways you can "break the rules" in software, such as using global variables -- and just because something is possible, that doesn't make it a good idea. If anything here, animals should be an object that CONTAINS dog1 and cat1, not be the the base class itself. - Tom Lord

1 Answers

1
votes

You need to make name_list a class variable

class Animal
  attr_accessor :name
  @@name_list = []

  def initialize
    @name = name
  end

 def set_name
   @name = gets
   puts "My name is #{@name}"
   @@name_list.push(@name.strip)
 end

 def self.show_all
   puts "List of your animals names: #{@@name_list}"
 end
end