Difference Between @@ and @ in Ruby

What is the difference between @@ and @ in Ruby?

A variable prefixed with @@ is a class variable and one prefixed with @ is an instance variable. A great description can be found in this answer: https://stackoverflow.com/a/5890199/1181886

Difference between .. and ... in Ruby

In ruby 1...5 gives you a range which doesn't include 5
whereas 1..5 gives you a range which does include 5

eg:

>> (1..5).to_a
[
[0] 1,
[1] 2,
[2] 3,
[3] 4,
[4] 5
]
>> (1...5).to_a
[
[0] 1,
[1] 2,
[2] 3,
[3] 4
]

What is the difference between @@ and @ and when should I use one rather than another?

@ is an instance variable. It is a variable attached to a particular object. These are how you store data on an object.

class Thing
# These two methods are basically what `attr_accessor :stuff` does.
def stuff=(value)
@stuff = value
end

def stuff
@stuff
end
end

f1 = Foo.new
f1.stuff = 42 # f1's @stuff is set to 42

f2 = Foo.new
f2.stuff = 23 # f2's @stuff is set to 23

p f1.stuff # 42
p f2.stuff # 23

@@ is a class variable. They are to be avoided because of a quirk: they're shared with all subclasses.

class Vehicle
@@type = 'vehicle'

def self.type
@@type
end
end

class Car < Vehicle
# This is the same @@type as in Vehicle
@@type = 'car'
end

class Plane < Vehicle
# This is the same @@type as in Vehicle
@@type = 'plane'
end

p Vehicle.type # plane
p Car.type # plane
p Plane.type # plane

Instead, use "class instance variables". Everything in Ruby is an object including classes. They are instances of Class. class Vehicle ... end is syntax sugar for Vehicle = Class.new do ... end. And like any object, they can have instance variables.

# Same as `class Vehicle` just to demonstrate.
Vehicle = Class.new do
# This is an instance variable on the Vehicle Class object.
# Not Vehicle.new, but just Vehicle.
@type = 'vehicle'

def self.type
@type
end
end

# class Plane < Vehicle
Plane = Class.new(Vehicle) do
# This is an instance variable on the Plane Class object.
@type = 'plane'
end

# And the sugary way.
class Car < Vehicle
# This is an instance variable on the Car Class object.
@type = 'car'
end

p Vehicle.type # vehicle
p Car.type # car
p Plane.type # plane

See Class Instance Variables in Ruby and The Official Ruby FAQ for more.

what is the difference between += and =+ in ruby?

There's no such token as =+; it's actually two tokens: assignment followed by the unary + operator; the latter is essentially a no-op, so @@num_things =+ 1 is equivalent to @@num_things = 1.

Since there is a += token, the language parser will parse it as a single token.

(In the early formulations of BCPL which was the precursor to C, the modern -= operator was written as =-.)

What's the difference between = & = and @variable, @@variable and :variable in ruby?

OK.

The difference between the = and the => operators is that the first is assignment, the second represents an association in a hash (associative array). So { :key => 'val' } is saying "create an associative array, with :key being the key, and 'val' being the value". If you want to sound like a Rubyist, we call this the "hashrocket". (Believe it or not, this isn't the most strange operator in Ruby; we also have the <=>, or "spaceship operator".)

You may be confused because there is a bit of a shortcut you can use in methods, if the last parameter is a hash, you can omit the squiggly brackets ({}). so calling render :partial => 'foo' is basically calling the render method, passing in a hash with a single key/value pair. Because of this, you often see a hash as the last parameter to sort of have a poor man's optional parameters (you see something similar done in JavaScript too).

In Ruby, any normal word is a local variable. So foo inside a method is a variable scoped to the method level. Prefixing a variable with @ means scope the variable to the instance. So @foo in a method is an instance level.

@@ means a class variable, meaning that @@ variables are in scope of the class, and all instances.

: means symbol. A symbol in Ruby is a special kind of string that implies that it will be used as a key. If you are coming from C#/Java, they are similar in use to the key part of an enum. There are some other differences too, but basically any time you are going to treat a string as any sort of key, you use a symbol instead.

what's difference between @ and @@ in a module?

Class variables can be shared between modules and classes where these modules are included.

module A
@@a = 5
end

class B
include A
puts @@a # => 5
end

Meanwhile, instance variables belong to self. When you include module A into class B, self object of A is not the same as self object of B, therefore you will not be able to share instance variables between them.

module A
@a = 5
end

class B
include A
puts @a # => nil
end

Difference between the @ instance variable belonging to the class object and @@ class variable in Ruby?

@one is an instance variable of the class MyClass and @@value is the class variable MyClass. As @one is an instance variable it is only owned by the class MyClass (In Ruby class is also object), not shareable, but @@value is a shared variable.

shared variable

class A
@@var = 12
end

class B < A
def self.meth
@@var
end
end

B.meth # => 12

non shared variable

class A
@var = 12
end

class B < A
def self.meth
@var
end
end

B.meth # => nil

@two is an instance variable of the instances of the class MyClass.

Instance variables are private property of objects, thus they wouldn’t share it. In Ruby classes are also objects. @one you defined inside a class MyClass, thus it is only owned by that class defining it. On the other hand @two instance variable will be created when you will be creating a object of the class MyClass, say ob, using MyClass.new. @two is only owned by ob, none other objects have any idea about it.

What does @@variable mean in Ruby?

A variable prefixed with @ is an instance variable, while one prefixed with @@ is a class variable. Check out the following example; its output is in the comments at the end of the puts lines:

class Test
@@shared = 1

def value
@@shared
end

def value=(value)
@@shared = value
end
end

class AnotherTest < Test; end

t = Test.new
puts "t.value is #{t.value}" # 1
t.value = 2
puts "t.value is #{t.value}" # 2

x = Test.new
puts "x.value is #{x.value}" # 2

a = AnotherTest.new
puts "a.value is #{a.value}" # 2
a.value = 3
puts "a.value is #{a.value}" # 3
puts "t.value is #{t.value}" # 3
puts "x.value is #{x.value}" # 3

You can see that @@shared is shared between the classes; setting the value in an instance of one changes the value for all other instances of that class and even child classes, where a variable named @shared, with one @, would not be.

[Update]

As Phrogz mentions in the comments, it's a common idiom in Ruby to track class-level data with an instance variable on the class itself. This can be a tricky subject to wrap your mind around, and there is plenty of additional reading on the subject, but think about it as modifying the Class class, but only the instance of the Class class you're working with. An example:

class Polygon
class << self
attr_accessor :sides
end
end

class Triangle < Polygon
@sides = 3
end

class Rectangle < Polygon
@sides = 4
end

class Square < Rectangle
end

class Hexagon < Polygon
@sides = 6
end

puts "Triangle.sides: #{Triangle.sides.inspect}" # 3
puts "Rectangle.sides: #{Rectangle.sides.inspect}" # 4
puts "Square.sides: #{Square.sides.inspect}" # nil
puts "Hexagon.sides: #{Hexagon.sides.inspect}" # 6

I included the Square example (which outputs nil) to demonstrate that this may not behave 100% as you expect; the article I linked above has plenty of additional information on the subject.

Also keep in mind that, as with most data, you should be extremely careful with class variables in a multithreaded environment, as per dmarkow's comment.

Difference between and and && in Ruby?

and is the same as && but with lower precedence. They both use short-circuit evaluation.

WARNING: and even has lower precedence than = so you'll usually want to avoid and. An example when and should be used can be found in the Rails Guide under "Avoiding Double Render Errors".

Difference between various variables scopes in ruby

  1. Class variables are the same for all instances, because they're class variables–associated with the class. Everything access the same variable, including each instance.

  2. No. Local variables are just that–local. They may be local to a function, or local to the class declaration, which is different than being a class variable. Locals in a class declaration go out of scope when the class declaration ends.

  3. That's because they're exactly the same–they're global. Global state is always evil; this is not a property of the language or environment. That said, some global state may be required–that's just the way it is. It makes sense to use global state when there's global state. The trick is to use global state properly, which is sometimes a non-trivial endeavor.

  4. That's just how Ruby is.

  5. One has already been given by Chris.

  6. I would think this question would be largely self-answering. Global when the entire world needs access. Instance when it's specific to a class instance. Local when it's only required in a local scope (e.g., a method, a block (note differences between 1.8 and 1.9 with regard to block scope), etc.) Constant when the variable isn't supposed to change. A class variable when it's something that either every instance needs, or if exposed via a class method, something tightly associated with a class.

  7. There is no "most use-cases", it totally depends on what you're doing with the variable. And public isn't the de facto choice in Java–it depends on the entity in question. Default Java scope is package-private (methods, properties). Which to use in Ruby depends entirely upon the use-case, noting that as with Java, and even more easily in Ruby, things can be circumvented.



Related Topics



Leave a reply



Submit