Instance variable: self vs @
Writing @age
directly accesses the instance variable @age
. Writing self.age
tells the object to send itself the message age
, which will usually return the instance variable @age
— but could do any number of other things depending on how the age
method is implemented in a given subclass. For example, you might have a MiddleAgedSocialite class that always reports its age 10 years younger than it actually is. Or more practically, a PersistentPerson class might lazily read that data from a persistent store, cache all its persistent data in a hash.
ruby should I use self. or @
When you use @lines
, you are accessing the instance variable itself. self.lines
actually goes through the lines
method of the class; likewise, self.lines = x
goes through the lines=
method. So use @
when you want to access the variable directly, and self.
when you want to access via the method.
To directly answer your question, normally you want to set the instance variables directly in your initialize
method, but it depends on your use-case.
Python self.variable vs private member instance variable
There is in fact a difference between those two variables:
Since __var_A
is defined in class Foo
instead of an individual member-function like __init__
, you can change it for all instances at once like this:
Foo._Foo__var_A = 2
This will not work for __var_B
since you define it individually per instance.
Note though, that changing __var_A
on an instance will not change it for everyone else, it will instead put a local override into the object itself:
foo2 = Foo()
foo2._Foo__var_A = 1
Foo._Foo__var_A = 2
(foo2._Foo__var_A, foo._Foo__var_A) # Returns: (1, 2)
Understanding the self keyword when referring to a class instance variable in a ruby?
tl;dr: foo = value
will always refer to a local variable foo
not the method call self.foo=(value)
.
I am assumed this is because I need the self keyword to refer to the instance variable, total
No, total
is a local variable, not an instance variable. @total
is an instance variable. A local variable lives for the current scope, like a single method call. An instance variable sticks with the object.
You need the self
keyword to refer to the method total=
. Let's dive in.
attr_accessor :total
declares two methods, total
and total=
. These are wrappers to get and set the instance variable @total
. The following code does the equivalent.
def total
@total
end
def total=(value)
@total = value
end
Note that the method is named total=
, this will become important in a moment.
With that in mind, let's look at your code.
def add(amount)
self.total = self.total + amount
end
(Almost) everything in Ruby is really a method call. The above is syntax sugar for calling the total=
method on self
.
def add(amount)
self.total=(self.total + amount)
end
Now what happens if we remove self
like so?
def add(amount)
total = total + amount
end
In Ruby, self
is optional. Ruby will figure out if total
means the method total
or the local variable total
. The local variable takes precedence and assignment is always to a local variable.
total = total + amount
works like so:
def add(amount)
total = self.total + amount
end
Assignment is always to a local variable.
To further illustrate, what if we declared total
first?
def add(amount)
total = 23
self.total = total + amount
end
The existing local variable total
takes precedence over the total()
method. total + amount
refers to the local variable total
and so cr.add(10); puts cr.total
will be 33.
total = ...
will always refer to the local variable total
. For this reason if you want to use method assignment you must explicitly use self.total=
. In other cases you can drop the self
. And avoid local variables with the same name as methods.
def add(amount)
# self.total = self.total + amount
self.total = total + amount
end
Why did I not need self in add_student?
Because there is no ambiguity. You're not assigning to a local variable roster
.
def add_student(student, grade)
roster[grade] = roster[grade] || []
roster[grade] << student
end
roster[grade]
is really self.roster.[]=(grade)
. You are calling self.roster
which returns a Hash
and then calling the []=
method on that Hash to give it a new key/value pair.
Similarly, roster[grade] << student
is self.roster.[](grade).<<(student). Get a
Hash, call [
[]](https://ruby-doc.org/core/Hash.html#method-i-5B-5D) on it to retrieve the
Arrayand call [
<<](https://ruby-doc.org/core/Array.html#method-i-3C-3C) on that
Array`.
def add_student(student, grade)
self.roster.[]=(grade) = self.roster.[](grade) || []
self.roster.[](grade).<<(student)
end
Yes, []
, []=
, and <<
are all methods names like any other.
A lot of Ruby mysteries go away once you understand the method calls under the syntax sugar and that things like []
, []=
, <<
and so on are method names.
Difference between using self.variable and _variable when init these variables
The difference is simple: Using self.label = [[UILabel alloc] init]
will actually invoke the method [self setLabel:[[UILabel alloc] init]]
, and using _label = [[UILabel alloc] init]
will directly assign the value to the instance variable.
In practice what this means is that using the dot syntax is usually the best as the method invoked probably handles a lot of stuff for you, including:
- Memory management: For example, if you declare a property with attribute 'strong' or 'retain', then the method invoked should retain the object assigned.
- Key-Value Coding notifications: Maybe the class is key-value coding compliant for the property, which means the invoked method will notify the changes to observer objects.
Why would you not use the dot syntax? There are two potential reasons:
- To avoid side effects: A good practice is to not use the dot syntax inside an initializer method. This is because we want to assign the value but don't want the other side effects of the invoked method for safety reasons.
- Performance: This is probably rare, but maybe you are trying to implement a method with high performance and using instance variables directly can save the cost of invoking a method.
If you want to know more, I recommend reading this iOS guide which describes in more detail the ideas I mention here.
Difference between self.variable name and classname.variable in python
If You want to count number of created Employee
, You have to create method which will invoke to every objects at all (not individually).
To do that, create method and decorate her with @staticmethod
. Notice that this method don't have self
in parenthesies. Moreover create variable (here: count
), which also invoke to every class object at all (without self.
before).
Finally put our count
variable inside __init__
method with += 1
equation (than every time when new Employee
will be created __init__
will add +1 to our variable). But remember to add Employee.
before count
here, to count every single create Employee
as a class population.
class Employee(object):
count = 0
@staticmethod
def status():
print(Employee.count)
def __init__(self, x):
self.x = x
Employee.count += 1
print("this method is executed")
print("Now, we have got", Employee.count, "Employees")
emp1 = Employee("John")
We can show up population number with :
print(emp1.count)
emp1.status()
print(Employee.count)
Related Topics
Trying to Learn/Understand Ruby Setter and Getter Methods
Oo Design in Rails: Where to Put Stuff
Ruby: What Does 'Require: False' in Gemfile Mean
Why Doesn't Ruby Support Method Overloading
How to Set Tls Context Options in Ruby (Like Openssl::Ssl::Ssl_Op_No_Sslv2)
What Are All the Common Ways to Read a File in Ruby
What's the Difference Between Uri.Escape and Cgi.Escape
How to Create Multiple Submit Buttons For the Same Form in Rails
No Increment Operator (++) in Ruby
How to Install Sqlite3 For Ruby on Windows
Difference Between Collection Route and Member Route in Ruby on Rails
What Are the Ruby Gotchas a Newbie Should Be Warned About
Limitations in Running Ruby/Rails on Windows
Getting the Hostname or Ip in Ruby on Rails
Ruby Style: How to Check Whether a Nested Hash Element Exists
How to Skip the First Line of a CSV File and Make the Second Line the Header