Can a class in ruby ​​store the number of instances of objects using @class_instance_variable, and not @@ class_variable?

I am trying to keep the number of instances of objects of this class inside the class that defines these objects.

First of all, I know the reflection of the code and ObjectSpace.each_object, but I would prefer not to use reflection and let the class itself "follow up".

I looked around and all the solutions found seemed to use @@ class_variables in the class definition, for example, the accepted answer to this question: How to get class instances in Ruby?

As I was still reading, I found that class variables in ruby ​​can behave very badly in some situations ... The biggest reason is this:

A class variable defined at the top level of the program inherits all classes. It behaves like a global variable.

source and more detailed information here: http://ruby.runpaint.org/variables#class

So, I tried to encode a class that stores the number of its created objects inside itself, using the class instance variable instead of the class variable, and it seems to work fine, but since I still learn about this "deep" language topics I would like to ask you whether I wrote the code correctly and / or makes sense:

class Pizza @orders = 0 def self.new @orders += 1 end def self.total_orders @orders end end new_pizza = Pizza.new #=> 1 special_pizza = Pizza.new #=> 2 fav_pizza = Pizza.new #=> 3 

One of my doubts is that overriding the Pizza.new method will β€œremove” some important functionality of the original .new method? (What does the original. New method offer? How can I "verify" the method code using reflection?) What else am I doing wrong or completely wrong in my approach and why?

thanks

edit: forgot to add this important bit:

As a way to better limit the amount of things, I would like the Pizza class to be able to calculate only during the creation of the object and not have the setter method in its @instance class variable, which can be accessed at any time in the code (Pizza.count = 1000). That is why I tried to redefine the "new."

I think this is the hardest part, because of which I ask myself: is my approach in the right direction or should I just stop treating these language mechanisms so much and instead add some logic to myself so that the calculation only happens if if an object of class Pizza introduced ObjectSpace ..

I'm just looking for a more elegant, not overblown way to get this using language features.

In any case, help would be appreciated.

Thanks again.

+4
source share
2 answers

You do not need to redefine new ones. Try the following:

 class Pizza @count = 0 class << self attr_accessor :count end def initialize self.class.count += 1 end end Pizza.new Pizza.new puts Pizza.count 

Please note that Pizza.count will not fall when the pizzas are garbage collected and they will not grow if they are dup ed.

To answer your other questions: I'm not sure how you can test the new method, but it is probably written in C, so you should look in the Ruby source code. I think that basically does it.

 def new(*args, &block) o = allocate o.initialize(*args, &block) o end 

At some point, you could leave with redefining the new ones while you call super . (Not to say that this is a good idea, but for example:

 class Foo def self.new # do whatever stuff you want here super end end 

)

+8
source

you're right. using class variables is stunning. I always forget if inherited or not, etc.

your approach is right, but ...

NEVER override new implement initialize ! it will be called during the init process of each object. see the docs here: http://apidock.com/ruby/v1_9_3_125/Class/new

0
source

Source: https://habr.com/ru/post/1439732/


All Articles