I have the following piece of code:
class Fish
# #message = "I can swim"
class << self
#message = "I can jump!"
define_method(:action) { #message }
end
end
Fish.action => nil
As soon as I uncomment the above #message variable, Fish.action returns I can swim. Why in both cases it is ignoring the I can jump message. Why is that? Why is Fish class being binded to the #message defined at the start but not inside the singleton class?
It's because class << self opens the class' singleton class context:
class Foo
p self # Foo
class << self
p self # #<Class:Foo>
define_method(:bar) { p self } # Foo
end
end
Foo.bar
You can verify that by:
Fish.singleton_class.instance_variable_get(:#action) # => "I can jump!"
Related
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
class MyClass
#my_class_instance_variable = "here"
p #my_class_instance_variable # => "here"
class << self
p #my_class_instance_variable # => nil
end
end
class MyClass
p #my_class_instance_variable # => "here"
end
Why does the second p print nil, when the third p prints "here"? My understanding of a singleton class definition (class << self) is that it has the same scope as a class definition (class MyClass).
(This question has a similar title, but it has a different focus.)
My understanding of a singleton class definition (class << self) is
that it has the same scope as a class definition
Nope. The scope is different. You defined #my_class_instance_variable in the scope of MyClass, but are trying to access it in the scope if MyClass's singleton class.
It is as easy to check as:
class Foo
puts self #=> Foo
class << self
puts self #=> #<Class:Foo>
end
end
With the output of:
Foo
#<Class:Foo>
Can someone explain why self.foo= works outside of the class << self, while foo= does not work within the class << self.
class A
class << self
attr_accessor :foo
foo = 'foo'
end
end
p A.foo # => "nil"
class A
class << self
attr_accessor :foo
end
self.foo = 'foo'
end
p A.foo # => "foo"
This is not the same question as When to use 'self' in Ruby
To be clear, I am not asking when to use self. I am asking why I cannot set the class variable inside a 'class << self' block, but I can outside of it.
your second example isn't a class variable, it's a class instance variable to this class the proof is that if you inherited like this you'll get nil
class A
class << self
attr_accessor :foo
end
self.foo = 'foo'
end
class B < A
end
B.foo # => nil
So if you want to add a class variable in class << self you can use ##
class A
class << self
##foo = :foo
def foo
##foo
end
end
end
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.
I have the following Ruby script, in which class Foo includes module Baz, module Baz has a included hook to make Bar extended by the including class (Foo). I am just wondering why:
class << klass
extend Bar #this doesn't work. Why?
end
does not work while:
klass.extend(Bar) works.
Here is my code:
#! /usr/bin/env ruby
module Baz
def inst_method
puts "dude"
end
module Bar
def cls_method
puts "Yo"
end
end
class << self
def included klass
# klass.extend(Bar) this works, but why the other approach below doesn't?
class << klass
extend Bar #this doesn't work. Why?
def hello
puts "hello"
end
end
end
end
end
class Foo
include Baz
end
foo = Foo.new
foo.inst_method
Foo.hello
Foo.cls_method
Within the body of class << klass, self refers to the singleton class of klass, not klass itself, whereas in klass.extend(Bar), the receiver is klass itself. The difference comes from there.
class A
end
class << A
p self # => #<Class:A> # This is the singleton class of A, not A itself.
end
p A # => A # This is A itself.
And since you want to apply extend to klass, doing it within the body of class << klass does not work.
What you want is invoke the extend method on the class object (klass) not the singleton class (class << klass).
Therefore the following code doesn't work because you are invoking the extend method on the singleton class:
class << klass
extend Bar # doesn't work because self refers to the the singleton class of klass
def hello
puts "hello"
end
end