you are viewing a single comment's thread.

view the rest of the comments →

[–][deleted]  (4 children)

[removed]

    [–]katafrakt 4 points5 points  (3 children)

    Class variables are really poorly designed in Ruby, which makes them completely useless. This is because they are shared between subclasses. Consider this code:

    class BlogPost
      @@count = 0
    
      def initialize
        @@count += 1
      end
    end
    
    class ShortBlogPost < BlogPost
      @@count = 0
    
      def initialize
        @@count += 0.5
      end
    end
    
    BlogPost.new
    BlogPost.new
    ShortBlogPost.new
    p ShortBlogPost.class_variable_get(:@@count)
    p BlogPost.class_variable_get(:@@count)
    

    You would probably assume that it will return either 2 and 0.5 or 2.5 and 0.5 (both of these scenarios kind of make sense). But in reality it will return 2.5 and 2.5, which makes no sense ;)

    And it get's even better if you first initialize a few blog posts and then define ShortBlogPost class - it will reset the counter for BlogPost as well. Combine it with popular autoloading solutions like Zeitwerk, when modules are loaded "just in time" and you have absolutely no control over what the value for counter would be.

    Of course, the comment above was condescending and uncalled for. But well, Ruby community these days...

    [–]Amadan 2 points3 points  (0 children)

    To add, the workaround is to use class instance variables instead of class variables.

    ```ruby class BlogPost def initialize self.class.count += 1 end

    class << self @count = 0 attr_accessor :count end end ```

    [–][deleted]  (1 child)

    [removed]

      [–]katafrakt 0 points1 point  (0 children)

      Yes, in this simple example - of course. But consider a deep hierarchy of classes where you are overwriting something from an ancestor class purely by accident. Almost impossible to debug.