Ruby Should I Use Self. or @

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.

In Ruby, when should you use self. in your classes?

Use self when calling a class's mutator. For example, this won't work:

class Foo
attr_writer :bar
def do_something
bar = 2
end
end

The problem is that 'bar = 2' creates a local variable named 'bar', rather than calling the method 'bar=' which was created by attr_writer. However, a little self will fix it:

class Foo
attr_writer :bar
def do_something
self.bar = 2
end
end

self.bar = 2 calls the method bar=, as desired.

You may also use self to call a reader with the same name as a local variable:

class Foo
attr_reader :bar
def do_something
bar = 123
puts self.bar
end
end

But it's usually better to avoid giving a local variable the same name as an accessor.

How and why should I avoid using self in a Ruby method declaration

There's nothing wrong with using self, but it bypasses the requirement to create a variable instance of your object, so some die-hard OO programmers would suggest avoiding self for that reason. If you avoid "self" then you are forced to initialize your class and assign it to a variable name which forces you think of it as a true object, and not just a collection of functions.

Here's an example class to demonstrate how you would call methods with and without "self"

class StaticVersusObjectMethod

def self.class_method
puts 'Hello, static class method world!'
end

def object_method
puts 'Hello, object-oriented world!'
end

end

# No need to create an object instance variable if the method was defined with 'self'
StaticVersusObjectMethod.class_method

# You must create an object instance variable to call methods without 'self'
object = StaticVersusObjectMethod.new
object.object_method

output:

Hello, static class method world!
Hello, object-oriented world!

Whether you use self in the declaration should depend on the data you want your method to use. If the methods will only operate on the variables you pass in as parameters, then use 'self'. On the other hand, don't use 'self' if you want them to act as true object methods. "True" object methods can operate on the state of the class variables (fields) in the objects which you create and assign to a one or more variable names.

When do I need to use self.instance_method vs instance_method alone?

There are a few differences between self.foo(...) and foo(...), but they're mostly equivalent.

Privacy

private methods can only be called via foo directly, and never with an explicit receiver. So if foo is marked private, then you have to call it without self.

class Example

private def foo(x)
x + 1
end

def bar
foo # Works fine
self.foo # Error: foo is private
end

end

Shadowing

If you have a local variable called foo in the current function, then writing foo without arguments will reference the local variable instead

class Example

def foo(*args)
puts "Hello :)"
end

def bar
foo = 100 # Just an ordinary variable; no relation to the above method
foo # This refers to the local variable called "foo"
self.foo # This calls the method foo() with no arguments
foo(1) # This calls the method foo() with one argument
self.foo(1) # Equivalent to the above; calls with one argument
end

def baz
foo # There's no local variable called "foo", so this calls the method
end

end

Assignment

If the method you're talking about is an assignment method (i.e. ends in =), then it must always be called with an explicit receiver

class Example

def foo=(value)
puts "Assigning foo = #{value}"
end

def bar
foo = 0 # This creates a new local variable called foo and assigns to it
self.foo = 0 # Calls foo= on self
end

end

To use self. or not.. in Rails

def self.method_name
end

defines a class method.

def method_name
end

defines an instance method.

This is a pretty good post on it.

When to use self in module's methods

Use self in each method definition if you want the methods to be defined only in the singleton class of the module (where the methods defined using self live). Omit self and extend self if you want the methods of the module to be defined as instance methods and singleton methods at the same time.

For instance, you can call the method using RG::Stats.sum(array) and still have it listed by the instance_methods method if you do this:

module RG::Stats
extend self

def sum(a, args = {})
a.inject(0){ |accum, i| accum + i }
end
end

This way, the sum method is defined as an instance method and it is included in the singleton class of the module after using extend self.

You can check the instance methods of RG::Stats module to verify this:

RG::Stats.instance_methods
=> [:sum]

With this technique you don't have to worry about defining the method without the self keyword because modules can't have instances so it cannot be called like an instance method of RG::Stats module. It can only be called as a singleton method RG::Stats.sum(array) thanks to the extend self statement.

When to use self for Ruby Class

The methods defined right inside a class block are instance methods:

class Foo
def bar
end
end

Methods defined within class << self inside a class block are class methods:

class Foo
class << self
def baz
end
end
end

Instance methods become available to any instance of a given class:

foo = Foo.new
foo.bar

Whereas class methods can be called directly on the class:

Foo.baz

Attempting to call instance methods on the class or vice versa results in an error:

Foo.bar #=> NoMethodError: undefined method `bar' for Foo:Class
foo.baz #=> NoMethodError: undefined method `baz' for #<Foo:0x00007ffe20055a20>

Another way to define class methods is by prefixing the method name with self.:

class Foo
def self.baz
end
end

You could also define them outside the class block, although this is rarely seen:

def Foo.baz
end

Or likewise:

class << Foo
def baz
end
end

Note that defining methods this way is not limited to classes. You can add methods to arbitrary objects, e.g.:

o = Object.new

def o.hello
"hello from o"
end

o.hello
#=> "hello from o"

Or via:

class << o
def hello
"hello from o"
end
end

Internally, these methods are added to the object's singleton class. It's a special purpose class to hold methods for just that instance:

o.singleton_class.instance_methods(false)
#=> [:hello]

For the Foo class above:

Foo.instance_methods(false)                 #=> [:bar]
Foo.singleton_class.instance_methods(false) #=> [:baz]

So technically, a class method is just an instance method defined on the class' singleton class.

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.

class self vs self.method with Ruby: what's better?

class << self is good at keeping all of your class methods in the same block. If methods are being added in def self.method form then there's no guarantee (other than convention and wishful thinking) that there won't be an extra class method tucked away later in the file.

def self.method is good at explicitly stating that a method is a class method, whereas with class << self you have to go and find the container yourself.

Which of these is more important to you is a subjective decision, and also depends on things like how many other people are working on the code and what their preferences are.

When to use 'self' in Ruby

Whenever you want to invoke a setter method on self, you have to write self.foo = bar. If you just write foo = bar, the ruby parser recognizes that as a variable assignment and thinks of foo as a local variable from now on. For the parser to realize, that you want to invoke a setter method, and not assign a local variable, you have to write obj.foo = bar, so if the object is self, self.foo = bar



Related Topics



Leave a reply



Submit