What does ##variable mean in Ruby? - ruby

What are Ruby variables preceded with double at signs (##)? My understanding of a variable preceded with an at sign is that it is an instance variable, like this in PHP:
PHP version
class Person {
public $name;
public function setName($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
Ruby equivalent
class Person
def set_name(name)
#name = name
end
def get_name()
#name
end
end
What does the double at sign ## mean, and how does it differ from a single at sign?

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.

# - Instance variable of a class
## - Class variable, also called as static variable in some cases
A class variable is a variable that is shared amongst all instances of a class. This means that only one variable value exists for all objects instantiated from this class. If one object instance changes the value of the variable, that new value will essentially change for all other object instances.
Another way of thinking of thinking of class variables is as global variables within the context of a single class.
Class variables are declared by prefixing the variable name with two # characters (##). Class variables must be initialized at creation time

## denotes a class variable, i.e. it can be inherited.
This means that if you create a subclass of that class, it will inherit the variable. So if you have a class Vehicle with the class variable ##number_of_wheels then if you create a class Car < Vehicle then it too will have the class variable ##number_of_wheels

The answers are partially correct because ## is actually a class variable which is per class hierarchy meaning it is shared by a class, its instances and its descendant classes and their instances.
class Person
##people = []
def initialize
##people << self
end
def self.people
##people
end
end
class Student < Person
end
class Graduate < Student
end
Person.new
Student.new
puts Graduate.people
This will output
#<Person:0x007fa70fa24870>
#<Student:0x007fa70fa24848>
So there is only one same ##variable for Person, Student and Graduate classes and all class and instance methods of these classes refer to the same variable.
There is another way of defining a class variable which is defined on a class object (Remember that each class is actually an instance of something which is actually the Class class but it is another story). You use # notation instead of ## but you can't access these variables from instance methods. You need to have class method wrappers.
class Person
def initialize
self.class.add_person self
end
def self.people
#people
end
def self.add_person instance
#people ||= []
#people << instance
end
end
class Student < Person
end
class Graduate < Student
end
Person.new
Person.new
Student.new
Student.new
Graduate.new
Graduate.new
puts Student.people.join(",")
puts Person.people.join(",")
puts Graduate.people.join(",")
Here, #people is single per class instead of class hierarchy because it is actually a variable stored on each class instance. This is the output:
#<Student:0x007f8e9d2267e8>,#<Student:0x007f8e9d21ff38>
#<Person:0x007f8e9d226158>,#<Person:0x007f8e9d226608>
#<Graduate:0x007f8e9d21fec0>,#<Graduate:0x007f8e9d21fdf8>
One important difference is that, you cannot access these class variables (or class instance variables you can say) directly from instance methods because #people in an instance method would refer to an instance variable of that specific instance of the Person or Student or Graduate classes.
So while other answers correctly state that #myvariable (with single # notation) is always an instance variable, it doesn't necessarily mean that it is not a single shared variable for all instances of that class.

# and ## in modules also work differently when a class extends or includes that module.
So given
module A
#a = 'module'
##a = 'module'
def get1
#a
end
def get2
##a
end
def set1(a)
#a = a
end
def set2(a)
##a = a
end
def self.set1(a)
#a = a
end
def self.set2(a)
##a = a
end
end
Then you get the outputs below shown as comments
class X
extend A
puts get1.inspect # nil
puts get2.inspect # "module"
#a = 'class'
##a = 'class'
puts get1.inspect # "class"
puts get2.inspect # "module"
set1('set')
set2('set')
puts get1.inspect # "set"
puts get2.inspect # "set"
A.set1('sset')
A.set2('sset')
puts get1.inspect # "set"
puts get2.inspect # "sset"
end
class Y
include A
def doit
puts get1.inspect # nil
puts get2.inspect # "module"
#a = 'class'
##a = 'class'
puts get1.inspect # "class"
puts get2.inspect # "class"
set1('set')
set2('set')
puts get1.inspect # "set"
puts get2.inspect # "set"
A.set1('sset')
A.set2('sset')
puts get1.inspect # "set"
puts get2.inspect # "sset"
end
end
Y.new.doit
So use ## in modules for variables you want common to all their uses, and use # in modules for variables you want separate for every use context.

Related

How can I access a superclass class variable from a subclass in Ruby

I am trying to access a class variable from a subclass. I understand that class variables are not inherited which answers the question of why the code does not work, however I don't fully understand how I can work around it.
This is my code:
Class A
...
class << self
def format(a, b)
#format = a
end
def item(a, b)
#item[a] = b
end
end
end
Class B < A
format 4, 7
item 7, 12
...
end
Class C < B
item 7, 18
end
Running the following in a irb session
B.format => 4
C.format => nil
So understanding that class variables aren't inherited, is it possible to make C.format => 4 or will I need to refactor as such:
Class B < A
format 4, 7
item 7, 12
end
Class C < A
format 4, 7
item 7, 18
end
My reason for wanting to avoid the latter is that I have a lot of variables defined in that same way (calling a function to set a class variable) and I don't want to have to duplicate all the code across class B and C because one instance variable differs.
I understand that class variables are not inherited
This is completely false and you have not actually understood what class variables are.
A class variable in Ruby is declared with the ## sigil. And they are definitely inherited:
class A
##x= "Hello World"
end
class B < A
puts ##x # Outputs "Hello World"
end
Class variables are actually shared between a class and its subclasses:
class Animal
##greating = "Hello"
def greet
"#{##greating} I'm a #{self.class.name.downcase}"
end
end
class Cat < Animal
##greating = "Meow"
end
class Dog < Animal
##greating = "Woof"
end
puts Dog.new.greet # Woof I'm a dog
puts Cat.new.greet # Woof I'm a cat
puts Animal.new.greet # Woof I'm a animal
As you can see from the example this can often lead to unexpected and undesireable effects. And class variables are not considered thread safe.
What you are actually setting is referred to as a class instance variable - this is just a instance variable except that its scope is not a instance of A. Instead its scope is the singleton class A which is an instance of the Class class.
Unlike true class variables which have their own sigil class instance variables are not shared between a class and its subclasses as thier scope is the singleton class. Every subclass its own singleton class.
class Animal
#greating = "Hello"
def self.greeting
#greating
end
def greet
"#{self.class.greeting} I'm a #{self.class.name.downcase}"
end
end
class Cat < Animal
#greating = "Meow"
end
class Dog < Animal
#greating = "Woof"
end
puts Dog.new.greet # Woof I'm a dog
puts Cat.new.greet # Meow I'm a cat
puts Animal.new.greet # Hello I'm a animal
Class instance variables are actually far more useful then true class variables. If you want to simulate the inheritance of class variables with class instance variables you can do it with the Class#inherited callback provided by Ruby:
class A
#x = [self.name]
class << self
attr_accessor :x
def inherited(subclass)
puts "#{subclass.name} is inheriting from #{self.name}"
subclass.x = x
subclass.x.push(subclass.name)
end
end
end
class B < A; end # outputs "B is inheriting from A"
class C < B; end # outputs "C is inheriting from B"
puts B.x.inspect # => ['A', 'B']
puts C.x.inspect # => ['A', 'B', 'C']
Firstly, to define a class you need to use the keyword class not Class.
Secondly, there is no reason to pass the method A::format an argument it does not use. I therefore changed it to have just one argument.
Thirdly, after defining A, when A.item is first executed an exception will be raised because #item has not been defined. Specifically, #item (like any other undefined instance variable) will return nil when called and nil has no no method []. I therefore changed the method item to initialize the class instance variable (not class variable) #item to an empty array.
class A
class << self
def format(a)
#format = a
end
def item(a, b)
#item = []
#item[a] = b
end
end
end
class B < A
format 4
item 7, 12
end
class C < B
item 7, 18
def self.format
superclass.instance_variable_get(:#format)
end
end
It is my understanding that you want a method C::format to return the value of B's instance variable #format.
C.format
#=> 4
If one attempts to execute B.format an exception will be raised because B::format requires two arguments. If B.format is meant to return the value of B's class instance variable #format you need to write:
B.instance_variable_get(:#format)
#=> 4
You might add read and write accessors for the the instance variable #format, in which case your code would be simplified somewhat:
class A
class << self
attr_accessor :format
def item(a, b)
#item = []
#item[a] = b
end
end
end
class B < A
#format = 4
item 7, 12
end
class C < B
item 7, 18
def self.format
superclass.format
end
end
C.format
#=> 4

Use current class in constant declaration

class Cat
SUPERSTARS = [Cat.new('John'), Cat.new('Alfred')]
attr_accessor :name
def initialize(name)
#name = name
end
end
I get an error
ArgumentError: wrong number of arguments(1 for 0)
because initialize is not again defined.
If I put the definition on the end:
class Cat
attr_accessor :name
def initialize(name)
#name = name
end
SUPERSTARS = [Cat.new('John'), Cat.new('Alfred')]
end
it works.
Is it possible to keep constant declaration on the top of the file?
I think, you can use this trick:
class Cat
def self.const_missing(name)
[Cat.new('John'), Cat.new('Alfred')] if name == :SUPERSTARS
end
attr_accessor :name
def initialize(name)
#name = name
end
end
Avdi Grimm in his free episode of rubytapas called "Barewords" recommends that you don't use constants directly. Instead, wrap them in a method. And when you have a method, you don't even need the constant (which in ruby is not really constant anyway).
So, you can do something like this:
class Cat
def self.superstars
#superstars ||= [Cat.new('John'), Cat.new('Alfred')]
end
attr_accessor :name
def initialize(name)
#name = name
end
end
The only difference is that you now call it Cat.superstars instead of Cat::SUPERSTARS. Your code now works and looks better too! I call it a win-win. :)
The problem is that class definitions are just code that gets executed when the definition is reached. It's like asking if you can access the value of a local variable that you have not yet defined.
A possible workaround is to delay the evaluation of the constant until the class body is executed. Note that it's not really worth it and it shows a working solution that shouldn't be used in practice:
# BasicObject for minimal amount of methods
class Retarded < BasicObject
def initialize(&value)
#value = value
end
# Make sure we remove as many methods as we can to
# make the proxy more transparent.
(instance_methods - %i(__id__ __send__ __binding__)).each do |name|
undef_method name
end
def method_missing(*args, &block)
# Get the actual value
value = #value.call
# Suppress warnings while we traverse constants
warn_level, $VERBOSE = $VERBOSE, nil
traversed_modules = []
constant_finder = -> (root) do
constant_name = root.constants.find do |constant|
# We undefed ==, so we need a different way to compare.
# Given that this class should be used for constant values in place,
# comparing object ids does the job.
root.const_get(constant).__id__ == __id__
end
if constant_name
# Just set the constant to the actual value
root.const_set(constant_name, value)
else
# Recursively search for the containing module of the constant
root.constants.each do |child_name|
child_constant = root.const_get(child_name)
if child_constant.is_a?(::Module) &&
!traversed_modules.include?(child_constant)
# Handle circular references
traversed_modules.push child_constant
constant_finder.(child_constant)
end
end
end
end
# ::Object is the root module where constants are contained
constant_finder.(::Object)
# Bring back warnings
$VERBOSE = warn_level
# We have already found the constant and set its value to whatever was
# passed in the constructor. However, this method_missing was called
# in an attempt to call a method on the value. We now should make that
# invocation.
value.public_send(*args, &block)
end
end
# I know, the example is mononic.
class EdwardKing
DEAD = Retarded.new { [new('I'), new('II'), new('III')] }
def initialize(number)
#number = number
end
def whoami
"Edward #{#number} of England"
end
end
p EdwardKing::DEAD
# [#<EdwardKing:0x007f90fc26fd10 #number="I">, #<EdwardKing:0x007f90fc26fc70 #number="II">, #<EdwardKing:0x007f90fc26fc20 #number="III">
p EdwardKing::DEAD.map(&:whoami)
# ["Edward I of England", "Edward II of England", "Edward III of England"]

Class method is accessing instance variable

I'd like to understand this code. Why is it returning Hello instead of Howdy! ?
class Speaker
#message = "Hello!"
class << self
#message = "Howdy!"
def speak
#message
end
end
end
puts Speaker.speak
First off, your message #message is not an instance variable, or rather not the type of instance variable you may be thinking about: it's a class-level instance var, so an instance variable of Speaker itself, which as an object is an instance of class Class.
Here's a version of the code that does what you're trying to do with a local variable and a closure:
class Speaker
#message = "Hello!"
class << self
message = "Howdy!"
define_method(:speak) { message }
end
end
Speaker.speak
#=> "Howdy!"
And here's some code that illustrates the difference between the class-level instance variable and a "normal" instance variable:
class Speaker
#message = 'Howdy!' # class-level instance variable
def initialize
#message = 'Hello!' # instance variable of Speaker's instances
end
def speak
#message
end
class << self
def speak
#message
end
end
end
Speaker.speak
#=> "Howdy!"
Speaker.new.speak
#=> "Hello!"
Here is your code, except I've defined the class method in the usual way (def self.speak...). As a class method is nothing more than an instance method defined on the class' singleton class, this change is merely a different way of creating the same class method. (If you doubt that, run the code below both ways.) I made that change because I thought it would make my explanation of what is happening clearer. I also added a puts statement.
class Speaker
#message = "Hello!"
def self.speak
puts "self=#{self}"
#message
end
class << self
#message = "Howdy!"
end
end
The first line of the class definition creates a class instance variable #message:
Speaker.instance_variables
#=> [:#message]
Speaker.instance_variable_get(:#message)
#=> "Hello!"
By constrast,
#message = "Howdy!"
creates an instance variable on Speaker's singleton class:
Speaker.singleton_class.instance_variables
#=> [:#message]
Speaker.singleton_class.instance_variable_get(:#message)
#=> "Howdy!"
Now invoke speak on Speaker:
Speaker.speak
# self=Speaker
#=> "Hello!"
As self #=> Speaker, speak is obviously returning the value of the class instance variable.
For speak to return the value of the instance variable defined on Speaker's singleton class we can write the following:
class Speaker
#message = "Hello!"
def self.speak
puts "self=#{self}"
puts "singleton_class = #{singleton_class}"
singleton_class.instance_variable_get :#message
end
class << self
#message = "Howdy!"
end
end
puts Speaker.speak
# self=Speaker
# singleton_class = #<Class:Speaker>
# Howdy!
In the last expression, because self equals Speaker and self is the implied receiver when there is no explicit receiver, "singleton_class is equivalent to Speaker.singleton_class.
The reason this code returns 'Hello' is that it is attempting to change an instance variable in a class << self block.
Class methods are for anything that does not deal with an individual instance of that class - instance variables are tied to individual instances of a class, and we can't change instance variables at a class level.
Instead of using an instance variable in the speak method, we should use a class variable (denoted by ##).
As an example, the following code will return 'Howdy!' -
class Speaker
##message = "Hello!"
class << self
##message = "Howdy!"
def speak
##message
end
end
end
puts Speaker.speak

Constant vs. instance variable vs. instance method

I have a base class A containing a public method which works with an array provided by descendants of A. The array is:
used only by the methods defined in the base class A
constant, but there are special cases in which it varies.
How should I approach the object design of the problem thus defined? I am still not sure myself where to store that array, whether in a constant, an instance variable or an instance method. Please show me how to do this.
Last time I was evil to a female newbie. This time over, I'll try to be nice.
Way one, using a constant:
A = Class.new
class B < A
FOO = [ :hello, :world ] # this is your array
end
# Access different constants defined in different descendants is tricky, like this:
class A
def foo_user
puts self.class.const_get :FOO
end
end
B.new.foo_user #=> [ :hello, :world ]
# Note theat you can't do this:
class A
def foo_user
puts FOO # this would look for FOO in A mother class only
end
end
B.new.foo_user #=> error
Way two, using an instance variable belonging to the subclasses of A:
A = Class.new
class B < A
#foo = [ "hello", "world" ]
end
# This way is more usable. I would go about it like this:
class A
class << self
attr_reader :foo # defining a reader class method
end
def foo
self.class.foo # delegating foo calls on the instances to the class
end
def foo_user
puts foo
end
end
B.new.foo_user #=> [ :hello, :world ]
Way three, using an instance method defined on the descendants:
A = Class.new
class B < A
def foo
[ "hello", "world" ]
end
end
# This way is also usable.
class A
def foo_user
puts foo
end
end
The choice between the way 2 (instance variable belonging to a descendant class) and 3 (method defined on a descendant class) depends on how flexible the value (the array) needs to be. Way 2 is most flexible, but way 3 takes less code.

Class-objects, singleton classes

I play with metaprogramming in ruby and I have a question. I have a class:
class Klass
class << self
#x = "yeah"
end
end
b = Klass.new
a = class << Klass; self; end
a.instance_eval "#x" #=> yeah
Klass.instance_eval "#x" #=> nil
Why? In variable a I have a singleton class, right? And Klass.instance_eval exec in context of a singleton class:
Klass.instance_eval "def yeah; puts 10; end"
Klass.yeah #=> 10
Also, Klass in interpreter points to context of class, yes? And a points to context of a singleton class?
And which indicates a.class_eval and a.instance_eval? I do:
a.instance_eval "def pops; puts 0; end"
a.class_eval "def popsx; puts 1; end"
a.pops #=> 0
a.popsx # FAIL
Klass.pops # FAIL
Klass.popsx #=> 1
b.pops; b.popsx # DOUBLE FAIL
and I do not understand this. Thanks!
First, while it seems like eigentclass is used by some people singleton class is more common term. Singleton class contains object-specific behavior for an object in Ruby. You can't create other instances of that class except the original object this singleton class belongs to.
Speaking about defining of methods inside different types of eval this article introduces nice rule for methods defined in instance_eval and class_eval:
Use ClassName.instance_eval to define class methods.
Use ClassName.class_eval to define instance methods.
That pretty much describes the situation.
There was a huge write-up about classes that are instances of Class class, their singleton classes that are subclasses of Class class and some other crazy stuff (not that much related to the problem). But as your question can be easily applied to regular objects and their classes (and it makes things much easier to explain), I decided to remove that all (though, you can still see that stuff in revisions history of the answer).
Let's look at regular class and instance of that class and see how that all works:
class A; end
a = A.new
Method definitions inside different types of eval:
# define instance method inside class context
A.class_eval { def bar; 'bar'; end }
puts a.bar # => bar
puts A.new.bar # => bar
# class_eval is equivalent to re-opening the class
class A
def bar2; 'bar2'; end
end
puts a.bar2 # => bar2
puts A.new.bar2 # => bar2
Defining object-specific methods:
# define object-specific method in the context of object itself
a.instance_eval { def foo; 'foo'; end }
puts a.foo # => foo
# method definition inside instance_eval is equivalent to this
def a.foo2; 'foo2'; end
puts a.foo2 # => foo2
# no foo method here
# puts A.new.foo # => undefined method `foo' for #<A:0x8b35b20>
Let's now look at singleton class of object a:
# singleton class of a is subclass of A
p (class << a; self; end).ancestors
# => [A, Object, Kernel, BasicObject]
# define instance method inside a's singleton class context
class << a
def foobar; 'foobar'; end;
end
puts a.foobar # => foobar
# as expected foobar is not available for other instances of class A
# because it's instance method of a's singleton class and a is the only
# instance of that class
# puts A.new.foobar # => undefined method `foobar' for #<A:0x8b35b20>
# same for equivalent class_eval version
(class << a; self; end).class_eval do
def foobar2; 'foobar2'; end;
end
puts a.foobar2 # => foobar2
# no foobar2 here as well
# puts A.new.foobar2 # => undefined method `foobar2' for #<A:0x8b35b20>
Now let's look at instance variables:
# define instance variable for object a
a.instance_eval { #x = 1 }
# we can access that #x using same instance_eval
puts a.instance_eval { #x } # => 1
# or via convenient instance_variable_get method
puts a.instance_variable_get(:#x) # => 1
And now to instance variables inside class_eval:
# class_eval is instance method of Module class
# so it's not available for object a
# a.class_eval { } # => undefined method `class_eval' for #<A:0x8fbaa74>
# instance variable definition works the same inside
# class_eval and instance_eval
A.instance_eval { #y = 1 }
A.class_eval { #z = 1 }
# both variables belong to A class itself
p A.instance_variables # => [:#y, :#z]
# instance variables can be accessed in both ways as well
puts A.instance_eval { #y } # => 1
puts A.class_eval { #z } # => 1
# no instance_variables here
p A.new.instance_variables # => []
Now if you replace class A with class Class and object a with object Klass (that in this particular situation is nothing more than instance of class Class) I hope you'll get explanation to your questions. If you still have some feel free to ask.
It's hard to completely answer your question (for a thorough explanation of Ruby's class model, look at Dave Thomas' excellent presentation), nevertheless:
With class_eval, you actually define instance methods - it's as if you were inside the body of the class. For example:
class Klass
end
Klass.class_eval do
def instance_method
puts 'instance method'
end
end
obj = Klass.new
obj.instance_method # instance method
With instance_eval, you actually define class methods - it's as if you were inside the body of the singleton (eigenclass) class of the given object (nota bene that classes are objects too in Ruby). For example:
Klass.instance_eval do
def class_method
puts 'class method'
end
end
Klass.class_method # class method
And in your case:
Klass.instance_eval "#x" does not work because #x is not part of Klass, it's part of Klass' singleton class:
class Klass
class << self
#x = "yeah"
end
puts #x
end
# prints nothing
a.instance_eval "#x" works fine because you evaluate "#x" in the context of the a singleton class that is connected with the singleton class of Klass class in which you defined the #x instance variable. How singleton classes can be interconnected can be illustrated by this example:
class Foo
end
f = class << Foo; self; end
g = class << Foo; self; end
f.instance_eval "def yeah; puts 'yeah'; end"
g.yeah # yeah
g.instance_eval "def ghee; puts 'ghee'; end"
f.ghee # ghee
Klass.instance_eval "def yeah; puts 10; end" defines a 'normal' class method. Therefore Klass.yeah works fine (see Klass.class_method in the previous example).
a.instance_eval "def pops; puts 0; end" defines a class method on the a singleton class. Therefore, a.pops actually means calling the pops class method (again, it's as if calling Klass.class_method).
a.popsx does not work because you would first have to create an instance of a to be able to call popsx on it (but is not possible to create a new instance of a singleton class).
Klass.pops does not work because there isn't any pops method defined in Klass' singleton class (pops is defined in a's singleton class).
Klass.popsx works because with a.class_eval "def popsx; puts 1; end" you have defined the popsx instance method which you then call on the Klass object. It is, in a way, similar to this example:
class Other
end
o = Other.new
Other.class_eval "def yeah; puts 'yeah'; end"
o.yeah # yeah
Hope it helps.

Resources