1

I use Python in day to day programming and going through Ruby now.

I am able to do something like this in Python where instance of class can access variable defined inside class also I can call the variable with my class name.

>>> class Animal:
...   name = "Python"
... 
>>> 
>>> a = Animal()
>>> a.name
'Python'
>>> Animal.name
'Python'

Whereas in Ruby I get error, why this is so.

    2.4.2 :033 > class Animal
    2.4.2 :034?>   leg = 4
    2.4.2 :035?>   @@hand = 2
    2.4.2 :036?>   @brain = 1
    2.4.2 :037?> end
     => 1 
    2.4.2 :038 > a = Animal.new
     => #<Animal:0x0000000000e4d2e8> 
    2.4.2 :039 > a.leg
    NoMethodError: undefined method `leg' for #<Animal:0x0000000000e4d2e8>
        from (irb):39
        from /home/cyborg/.rvm/rubies/ruby-2.4.2/bin/irb:11:in `<main>'
    2.4.2 :040 > a.hand
    NoMethodError: undefined method `hand' for #<Animal:0x0000000000e4d2e8>
        from (irb):40
        from /home/cyborg/.rvm/rubies/ruby-2.4.2/bin/irb:11:in `<main>'
    2.4.2 :041 > a.brain
    NoMethodError: undefined method `brain' for #<Animal:0x0000000000e4d2e8>
        from (irb):41
        from /home/cyborg/.rvm/rubies/ruby-2.4.2/bin/irb:11:in `<main>'
    2.4.2 :047 > Animal.hand
NoMethodError: undefined method `hand' for Animal:Class
    from (irb):47
    from /home/cyborg/.rvm/rubies/ruby-2.4.2/bin/irb:11:in `<main>'
cyborg
  • 870
  • 1
  • 15
  • 34
  • leg is a local variable unaccessible from outside. try `puts a.hand` `puts a.brain` – Attersson May 12 '18 at 14:30
  • @Attersson same error – cyborg May 12 '18 at 14:32
  • 1
    ruby doesn't let you access class and instance variables from the outside like python does. You need to use explicit setters and getters. See the explanations [here](https://stackoverflow.com/questions/4370960/what-is-attr-accessor-in-ruby) and [here](https://stackoverflow.com/questions/5046831/why-use-rubys-attr-accessor-attr-reader-and-attr-writer) – bunji May 12 '18 at 14:38
  • 1
    @bunji Thanks, got clarified – cyborg May 12 '18 at 14:40

2 Answers2

4

In Python, static variables (actually, all attributes) of a class are always public. Heck, Python does not distinguish between public and private. Privacy is just a matter of convention[1]. As such, you can easily access name in Animal.

However, in Ruby, class variables cannot be accessed outside the class. They're private by default[2]. Everything goes through methods that return values of variables and sets them also[3].

So, if you want access class variables, you just need to create getter/setter methods for your class[4]. Like the one below.

class Animal
    @@hand = 2

    def hand
        @@hand
    end

    def hand=some_val
        @@hand = some_val
    end
end

irb> a = Animal.new
irb> a.hand
=> 2
irb> a.hand = 1
irb> a.hand
=> 1 

For instance variables, like what Daniel Roseman said, use attr_accessor.


References

Sean Francis N. Ballais
  • 2,338
  • 2
  • 24
  • 42
2

This has nothing to do with static variables.

All attributes in Ruby classes are private. If you want to access then from outside, you need an accessor method - which is why the errors talk about missing methods.

A shortcut to creating an accessor is to use the attr_accessor method.

Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895