4

I thought, and tried, using @i and self.i interchangeably, but it gives an error:

class Animal
    def initialize i
        @i = i
    end
    def get_i
        self.i
    end
end
a = Animal.new("Sparky")
puts a.get_i()

Outputs:

source_file.rb:8:in `get_i':
undefined method `i' for #<Animal:0x000000010d5330 @i="Sparky"> 
    (NoMethodError)  
    from source_file.rb:12:in `<main>' 

Is there any difference in terms of how the interpreter handles the code?

S.S. Anne
  • 15,171
  • 8
  • 38
  • 76
  • You should stick to either naming the variables and method either `@x`, `self.x` or `@i`, `self.i`. Mixing those two in your title and code just leads to unnecessary confusion. – Viktor Sep 27 '19 at 20:52
  • You ask for `x` in your title and question but have `i` in your code – Viktor Sep 27 '19 at 21:01
  • Yeah, I might have worded it poorly, sorry about that. – Viktor Sep 27 '19 at 21:06

1 Answers1

11

There is, of course, a difference betwenn self.i and @i:

  • @i will return the value assigned to the variable @i.
  • Whereas self.i will return the value which was returned by a method named i.

Your Animal class has no i method defined, therefore the error message is correct.

When you want self.i to return the value of the @i variable then you need to create a i method like this

def i
  @i
end

or simply use the attr_reader macro like this:

class Animal
  attr_reader :i

  #...
end
spickermann
  • 100,941
  • 9
  • 101
  • 131
  • the `attr_reader` macro is for a _list_ of getters! just use the simple getter you mentioned first. –  Sep 27 '19 at 21:10
  • 1
    @SapphireBrick I don't get you comment. The `attr_reader` can accept multiple arguments, but passing a single one is still valid. – 3limin4t0r Sep 28 '19 at 12:49
  • valid, but almost no advantage. The reason it exists is to save _many_ lines of code when multiple getters are necessary. –  Sep 29 '19 at 00:02
  • `attr_reader` is not only saving a few lines of code and makes the code easier to read and to understand – what IMHO is already a great benefit. These macros are a [common Ruby idiom](https://rubystyle.guide/#attr_family) and the are implemented in `C` and therefore [faster](https://stackoverflow.com/questions/13494098/ruby-attr-accessor-vs-getter-setter-benchmark-why-is-accessor-faster) than the pure Ruby getter or setter methods which they replace. Therefore I recommend already using the different `attr_` instead of trivial getter and setter methods. – spickermann Sep 29 '19 at 05:29
  • no, on the contrary, it might confuse Ruby newbies; They'll wonder what it does. also, what does _faster_ matter if it's only executing it once, and you're only gaining like 10 ^ -6 of a second. `atrr_reader` is a wonderful thing, but using it in that situation is like driving to your around-the-corner Supermarket. –  Sep 29 '19 at 16:46