When we are defining getter and setter methods for name
in the following code:
class Animal
attr_accessor :name
def initialize(name)
@name = name
end
end
what is happening internally? How is Ruby able to take a symbol and match it with a variable?
It uses instance_variable_get
and instance_variable_set
for that.
Update: as Andrew Marshall noted, not exactly. Most ruby core methods are defined in C, but the result is essentially the same.
One could define attr_accessor
and friends as follows:
def self.attr_accessor(*names)
names.each do |name|
define_method(name) do
instance_variable_get("@#{name}")
end
define_method("#{name}=") do |new_value|
instance_variable_set("@#{name}", new_value)
end
end
end
Note that I've also used define_method
here to define the accessor methods.
I recommend that you take a look at some introductory texts about ruby metaprogramming, such as "Don’t Know Metaprogramming In Ruby?".
It doesn't match it with a variable, attr_accessor
does essentially this (it's actually written in C, but I've written it's roughly Ruby translation here):
def attr_accessor(var_name)
ivar_name = :"@#{var_name}"
define_method(var_name) do
instance_variable_get ivar_name
end
define_method("#{var_name}=") do |value|
instance_variable_set ivar_name, value
end
end
As you can see, it simply uses the symbol passed to create two methods. It doesn't do anything fancy with the symbol, and is mostly just passing it through. Note, also, that all instance variables "exist" by default and are set to nil
, so this will never blow up.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With