Trying to learn / understand Ruby setter and getter methods
You can interact with that instance variable from other methods belonging to that instance, even if there is no getter:
def noise=(noise)
@noise = noise
end
def last_noise
@noise
end
There doesn't need to be a getter defined with the same name as the method; the two are not linked at all. The getter is needed to "get" the value of the instance variable, but only in a short syntax.
What's happening in your example is that you're initializing a new object (Human.new
), and then using a method (noise=
, yes the method name contains the =
symbol) that just-so-happens to define an instance variable (that is, a variable just for that instance), and then finally retrieving that instance variable with another method call.
You can actually use instance_variable_get
to get the instance variable without defining any getter at all:
man = Human.new
man.noise = "Howdie"
man.instance_variable_get("@noise")
This will return "Howdie", even though there is no getter defined.
And no, I don't think he's using an older version of Ruby.
Im trying to understand Getters and Setters in the ruby programming language
Understanding attr_accesor, attr_reader and attr_writer
These are Ruby's getters and setters shortcut. It works like C# properties, that injects the get_Prop
(getter) and set_Prop
(setter) methods.
attr_accessor
: injectsprop
(getter) andprop=
(setter) methods.attr_reader
: it's a shortcut for read-only properties. Injectsprop
method. Theprop
value can only be changed inside the class, manipulating the instance variable@prop
.attr_writer
: it's a shortcut for write-only properties. Injectsprop=
method.
Ruby doesn't have methods called get_prop
(getter) and set_prop
(setter), instead, they're called prop
(getter) and prop=
(setter).
That being said, you can infer that
class Person
attr_accessor :name, :age
end
is the short version for
class Person
# getter
def name
return @name
end
# setter
def name=(value)
@name = value
end
end
You don't need to call return
, Ruby methods returns the last executed statement.
If you are using Ruby on Rails gem, you can build model objects using new
and passing properties values as arguments, just like:
p = Person.new(name: 'Vinicius', age: 18)
p.name
=> 'Vinicius'
That's possible because Rails injects something like this initialize
method to ActiveRecord::Base
and classes that includes ActiveModel::Model
:
def initialize(params)
params.each do |key, value|
instance_variable_set("@#{key}", value)
end
end
Ruby/Rails: Understanding ruby getter-setter methods and instances
When you do
@dog = Dog.new
You do two spearate things
1) Create an instance variable @dog for whatever object your code is currently inside
2) Instantiate a new instance of Dog (with all its methods and attributes) and assign a reference to it to @dog
@dog is a variable, that just happens to point at the Dog instance ("instance of class" generally same meaning as "object") you created at that point. You can set other variables to point to the same instance, and in Ruby this is generally how you pass data around. Objects contain instance variables, and those instance variables point to yet more objects.
Using the assignment operator (i.e "=") you can point a variable at any other object.
To answer your questions in turn:
When I am in the owner class and I call @dog.popularity how does it
know the value of popularity for that instance?
You have to be careful in Ruby (and OO languages in general) to differentiate between class and object in your descriptions and questions. Ruby I'm assuming you are referring to a line of code in the Owner class, and that you intend it to work with an owner object. I'd also assume that @dog is an attribute you have added to Owner.
In which case, Ruby knows because @dog points to the Dog object that you added to owner. Each Dog object has its own copy of all of Dog's instance variables. You do need to take care in Ruby though, because variables point to objects, that you aren't simply passing in the same Dog object to all the owners (i.e. they all effectively share a single dog). So you need to understand when you are creating new instances (via new) and when you are simply handling existing references.
At runtime are all methods processed and then that instance just
always is tied to the value at the time?
No. At runtime, basic Ruby will only perform the assignments that you have coded. Instance variables may not even exist until the code that assigns them has been run. If you use attr_reader etc methods, then the variables will at least exist (but will be nil unless you assign something during initialize)
Calling setters and getters
In your example:
book01.isbn=("9876")
book01.isbn= "9876"
book01.isbn = "9876"
The last 2 examples are 'syntactic sugar', which are things that technically aren't proper syntactically but are kept in the language because they keep the code cleaner. The first example is the only way that would work if Ruby didn't support syntactic sugar. Why?
Because attr_acccessor :isbn behind the hood creates the following code for you:
def isbn
@isbn
end
def isbn=(new_isbn)
@isbn = new_isbn
end
These are 2 totally different methods, this might be confusing because the only difference in name is the = sign. But that doesn't mean anything, and doesn't change the fact they are totally different methods.
So with:
book01.isbn=("9876")
you're actually calling def isbn=(new_isbn) which is a method, nothing more, nothing else. And with:
book01.isbn= "9876"
book01.isbn = "9876"
you're just calling the SAME method, just using 'syntactic sugar'. Behind the hood, Ruby sees all of these 2 as:
book01.isbn=("9876")
Can you guess why this code will not work?
book01.isbn("9876")
Because, as we saw earlier, behind the hood Ruby creates 2 methods. The first method doesn't accept ANY arguments, therefore, you get the error you're getting (Ruby is just telling you, I expected 0 arguments, and you provided 1, therefore I raised ArgumentError).
In the latest version of Ruby, is having both getter and setter methods necessary to access instance variables?
puts noise = "roar"
This line has nothing to do with the previous lines - not with the class Carnivore, not with the instance carnivore. It creates a local variable noise (and prints it). Start experimenting with
puts carnivore.noise
Do Ruby objects have a built in getter/setter methods?
You're looking for attr_accessor :color
if you want just the run of the mill auto-generated getters/setters.
Defines a named attribute for this module, where the name is symbol.id2name, creating an instance variable (@name) and a corresponding access method to read it. Also creates a method called name= to set the attribute. String arguments are converted to symbols.
There's also just an attr_reader :color
if you don't want to be able to set the value outside the class
Creates instance variables and corresponding methods that return the value of each instance variable.
And attr_writer :color
if you want to set, but not read, outside of the class.
Creates an accessor method to allow assignment to the attribute.
class Obj
attr_accessor :color
def initialize(color)
@color = color
end
end
t = Obj.new("red")
t.color #=> "red"
Ruby square bracket setter/getter
Yes, it can be done. You need to define a []=
and []
methods.
In this example, I am using a Hash
as the internal data structure - you are free to use whatever you like.
class Word
attr_reader :meaning
def initialize
@meaning = Meaning.new
end
end
class Meaning
attr_reader :h
def initialize
@h = {}
end
def []=(key, value)
@h[key] = value
end
def [](key)
@h[key]
end
end
Example:
word = Word.new
word.meaning[:english] = 'Hello'
word.meaning[:english] # => 'Hello'
Related Topics
How to Use the Conditional Operator (? :) in Ruby
When to Use Lambda, When to Use Proc.New
What's the Difference Between Uri.Escape and Cgi.Escape
Ruby Multiline Block Without Do End
An How to Support Tags in a Jekyll Blog
How to Extract Url Parameters from a Url With Ruby or Rails
How to Convert a String or Integer to Binary in Ruby
Why Is the Shovel Operator (≪≪) Preferred Over Plus-Equals (+=) When Building a String in Ruby
Why Is This Rmagick Call Generating a Segmentation Fault
What Does the Question Mark At the End of a Method Name Mean in Ruby
Find_Spec_For_Exe': Can't Find Gem Bundler (≫= 0.A) (Gem::Gemnotfoundexception)