Ruby Class Methods vs. Methods in Eigenclasses - ruby

Are class methods and methods in the eigenclass (or metaclass) of that class just two ways to define one thing?
Otherwise, what are the differences?
class X
# class method
def self.a
"a"
end
# eigenclass method
class << self
def b
"b"
end
end
end
Do X.a and X.b behave differently in any way?
I recognize that I can overwrite or alias class methods by opening the eigenclass:
irb(main):031:0> class X; def self.a; "a"; end; end
=> nil
irb(main):032:0> class X; class << self; alias_method :b, :a; end; end
=> #<Class:X>
irb(main):033:0> X.a
=> "a"
irb(main):034:0> X.b
=> "a"
irb(main):035:0> class X; class << self; def a; "c"; end; end; end
=> nil
irb(main):036:0> X.a
=> "c"

The two methods are equivalent. The 'eigenclass' version is helpful for using the attr_* methods, for example:
class Foo
#instances = []
class << self;
attr_reader :instances
end
def initialize
self.class.instances << self
end
end
2.times{ Foo.new }
p Foo.instances
#=> [#<Foo:0x2a3f020>, #<Foo:0x2a1a5c0>]
You can also use define_singleton_method to create methods on the class:
Foo.define_singleton_method :bim do "bam!" end

In Ruby there really are no such things as class methods. Since everything is an object in Ruby (including classes), when you say def self.class_method, you are just really defining a singleton method on the instance of the class Class. So to answer your question, saying
class X
def self.a
puts "Hi"
end
class << self
def b
puts "there"
end
end
end
X.a # => Hi
X.b # => there
is two ways of saying the same thing. Both these methods are just singeton (eigen, meta, ghost, or whatever you want to call them) methods defined in the instance of your Class object, which in your example was X. This topic is part of metaprogramming, which is a fun topic, that if you have been using Ruby for a while, you should check out.
The Pragmatic Programmers have a great book on metaprogramming that you should definitely take a look at if you interested in the topic.

Yet another necromancer here to unearth this old question... One thing you might not be aware of is that marking a class method as private (using the private keyword instead of :private_class_method) is different than marking an eigenclass method as such. :
class Foo
class << self
def baz
puts "Eigenclass public method."
end
private
def qux
puts "Private method on eigenclass."
end
end
private
def self.bar
puts "Private class method."
end
end
Foo.bar
#=> Private class method.
Foo.baz
#=> Eigenclass public method.
Foo.qux
#=> NoMethodError: private method `qux' called for Foo:Class
# from (irb)
The following example will work how the previous one intends:
class Foo
class << self
def baz
puts "Eigen class public method."
end
private
def qux
puts "Private method on eigenclass."
end
end
def bar
puts "Private class method."
end
private_class_method :bar
end
Foo.bar
#=> NoMethodError: private method `bar' called for Foo:Class
# from (irb)
Foo.baz
#=> Eigen class public method.
Foo.qux
#=> NoMethodError: private method `qux' called for Foo:Class
# from (irb)

Most instance methods used in Ruby are global methods. That means they are available in all instances of the class on which they were defined. In contrast, a singleton method is implemented on a single object.
There is an apparent contradiction. Ruby stores methods in classes and all methods must be associated with a class. The object on which a singleton method is defined is not a class (it is an instance of a class). If only classes can store methods, how can an object store a singleton method? When a singleton method is created, Ruby automatically creates an anonymous class to store that method. These anonymous classes are called metaclasses, also known as singleton classes or eigenclasses. The singleton method is associated with the metaclass which, in turn, is associated with the object on which the singleton method was defined.
If multiple singleton methods are defined within a single object, they are all stored in the same metaclass.
class Zen
end
z1 = Zen.new
z2 = Zen.new
def z1.say_hello # Notice that the method name is prefixed with the object name
puts "Hello!"
end
z1.say_hello # Output: Hello!
z2.say_hello # Output: NoMethodError: undefined method `say_hello'…
In the above example, the say_hello method was defined within the z1 instance of the Zen class but not the z2 instance.
The following example shows a different way to define a singleton method, with the same result.
class Zen
end
z1 = Zen.new
z2 = Zen.new
class << z1
def say_hello
puts "Hello!"
end
end
z1.say_hello # Output: Hello!
z2.say_hello # Output: NoMethodError: undefined method `say_hello'…
In the above example, class << z1 changes the current self to point to the metaclass of the z1 object; then, it defines the say_hello method within the metaclass.
Both of the above examples serve to illustrate how singleton methods work. There is, however, an easier way to define a singleton method: using a built-in method called define_singleton_method.
class Zen
end
z1 = Zen.new
z2 = Zen.new
z1.define_singleton_method(:say_hello) { puts "Hello!" }
z1.say_hello # Output: Hello!
z2.say_hello # Output: NoMethodError: undefined method `say_hello'…
We learned earlier that classes are also objects (instances of the built-in class called Class). We also learned about class methods. Class methods are nothing more than singleton methods associated with a class object.
One more example:
class Zabuton
class << self
def stuff
puts "Stuffing zabuton…"
end
end
end
All objects may have metaclasses. That means classes can also have metaclasses. In the above example, class << self modifies self so it points to the metaclass of the Zabuton class. When a method is defined without an explicit receiver (the class/object on which the method will be defined), it is implicitly defined within the current scope, that is, the current value of self. Hence, the stuff method is defined within the metaclass of the Zabuton class. The above example is just another way to define a class method.
Read more at this post about Ruby Classes.

Related

When to use self for Ruby Class

Can somebody help me distinguish When we create methods inside class << self block and when we define normal methods.
I saw somewhere code like this, but I don't know concisely the use cases of them
class Foo
def initialize
end
def bar
end
class << self
def foobar
end
end
end
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.
You may need to read up on Ruby's instance and class methods.
But personally, I'd do
class Foo
class << self
def foobar
end
end
end
instead of
class Foo
def self.foobar
end
end
whenever I want to add some class level attributes, or make a method private etc as
class Foo
private
def self.foobar
end
end
wouldn't work the same as
class Foo
class << self
private
def foobar
end
end
end

Deep into Ruby class_eval and instance_eval

class_eval and instance_eval are quite predictable in such cases like defining methods. I also understand the difference between class's instance and class's singleton (aka eigenclass).
BUT
I cannot figure out the only thing like following:
Let's say, for some strage purposes, we want make existing class to be singleton.
class A; end
class B; end
A.class_eval do
private :new
end
B.instance_eval do
private :new
end
in both cases got
NameError: undefined method 'new' for class
Did you mean? new
yes, I mean exactly this method.
Moreover, these two variants give the same result, like self points at class object in both cases
A.class_eval do
class << self
private :new
end
end
A.new
=> NoMethodError: private method 'new' called for A:Class
B.instance_eval do
class << self
private :new
end
end
B.new
=> NoMethodError: private method 'new' called for B:Class
How come? Can anybody shed the light on this?
Lets take a peek into what self is here:
class A
puts self.inspect
class << self
puts self.inspect
end
end
A.class_eval {
puts self.inspect
class << self
puts self.inspect
end
}
A.instance_eval{
puts self.inspect
class << self
puts self.inspect
end
}
We get the following output:
A
#<Class:A>
A
#<Class:A>
A
#<Class:A>
The class_eval method is defined for modules (and thus classes) and evaluates within the context of the module (class). The instance_eval method evaluates within the context of a BasicObject. It seems that in these cases the two (three actually) are the same thing.
However, I know for a fact that if methods are created inside the eval block that class_eval creates instance methods and instance_eval creates class methods. There is already an excellent posting for that observation:

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.

Ruby Singleton methods for class and objects

I am learning Ruby Singletons and i found some ways to define and get list of Class and Object singleton methods.
Class Singleton Methods
Ways to define class singleton methods:
class MyClass
def MyClass.first_sing_method
'first'
end
def self.second_sing_method
'second'
end
class << self
def third_sing_method
'third'
end
end
class << MyClass
def fourth_sing_method
'fourth'
end
end
end
def MyClass.fifth_sing_method
'fifth'
end
MyClass.define_singleton_method(:sixth_sing_method) do
'sixth'
end
Ways to get list of class singletons methods:
#get singleton methods list for class and it's ancestors
MyClass.singleton_methods
#get singleton methods list for current class only
MyClass.methods(false)
Object Singleton Methods
Ways to define object singleton methods
class MyClass
end
obj = MyClass.new
class << obj
def first_sing_method
'first'
end
end
def obj.second_sing_method
'second'
end
obj.define_singleton_method(:third_sing_method) do
'third'
end
Way to get list of object singleton methods
#get singleton methods list for object and it's ancestors
obj.singleton_methods
#get singleton methods list for current object only
obj.methods(false)
Are there other ways to do this?
First of all, the way to list singleton methods is with singleton_methods. The methods method returns a list of the names of public and protected methods of the object. Also, it is defined in the Object class. Try extending an instance. It is one of the most elegant ways, as it supports code reuse and seems to me very object-oriented:
class Foo
def bar
puts "Hi"
end
end
module Bar
def foo
puts "Bye"
end
end
f = Foo.new
f.bar
#=> hi
f.extend Bar
f.foo
#=> bye
f.methods(false)
#=> []
# the module we extended from is not a superclass
# therefore, this must be empty, as expected
f.singleton_methods
#=> ["foo"]
# this lists the singleton method correctly
g = Foo.new
g.foo
#=> NoMethodError
Edit: In the comment you asked why methods(false) returns nothing in this case. After reading through the C code it seems that:
methods returns all the methods available for the object (also the ones in included modules)
singleton_methods returns all the singleton methods for the object (also the ones in included modules) (documentation)
singleton_methods(false) returns all the singleton methods for the object, but not those declared in included modules
methods(false) supposedly returns the singleton methods by calling singleton_methods, but it also passes the parameter false to it; whether this is a bug or a feature - I do not know
Hopefully, this clarifies the issue a little. Bottom line: call singleton_methods, seems more reliable.
Some more ways:
Class singleton methods
class << MyClass
define_method :sixth_sing_method do
puts "sixth"
end
end
class MyClass
class << self
define_method :fourth_sing_method do
puts "seventh"
end
end
end
Object singleton methods
class << obj
define_method :fourth_sing_method do
puts "fourth"
end
end
Next, you can use define_method and define_singleton_method in combination with send, e.g.
obj.send :define_singleton_method, :nth_sing_method, lambda{ puts "nth" }
and all possible combinations thereof. To use define_method, you need to capture the singleton class first as in this (the same works for class objects, too)
singleton_class = class << obj; self end
singleton_class.send :define_method, :nth_sing_method, lambda{ puts "nth" }
Another ways is using class_eval on the singleton class objects:
singleton_class.class_eval do
def nth_sing_method
puts "nth"
end
end
And then you once again may combine send with class_eval...
There are myriads of ways, I guess :)
Object singleton methods
instance_eval
class A
end
a = A.new
a.instance_eval do
def v
"asd"
end
end
a.singleton_methods
=> [:z, :v]

Remove/undef a class method

You can dynamically define a class method for a class like so:
class Foo
end
bar = %q{def bar() "bar!" end}
Foo.instance_eval(bar)
But how do you do the opposite: remove/undefine a class method? I suspect Module's remove_method and undef_method methods might be able to be used for this purpose, but all of the examples I've seen after Googling for hours have been for removing/undefining instance methods, not class methods. Or perhaps there's a syntax you can pass to instance_eval to do this as well.
Thanks in advance.
class Foo
def self.bar
puts "bar"
end
end
Foo.bar # => bar
class <<Foo
undef_method :bar
end
# or
class Foo
singleton_class.undef_method :bar
end
Foo.bar # => undefined method `bar' for Foo:Class (NoMethodError)
When you define a class method like Foo.bar, Ruby puts it Foo's singleton class. Ruby can't put it in Foo, because then it would be an instance method. Ruby creates Foo's singleton class, sets the superclass of the singleton class to Foo's superclass, and then sets Foo's superclass to the singleton class:
Foo -------------> Foo(singleton class) -------------> Object
super def bar super
There are a few ways to access the singleton class:
class <<Foo,
Foo.singleton_class,
class Foo; class << self which is commonly use to define class methods.
Note that we used undef_method, we could have used remove_method. The former prevents any call to the method, and the latter only removes the current method, having a fallback to the super method if existing. See Module#undef_method for more information.
This also works for me (not sure if there are differences between undef and remove_method):
class Foo
end
Foo.instance_eval do
def color
"green"
end
end
Foo.color # => "green"
Foo.instance_eval { undef :color }
Foo.color # => NoMethodError: undefined method `color' for Foo:Class
You can remove a method in two easy ways. The drastic
Module#undef_method( )
removes all methods, including the inherited ones. The kinder
Module#remove_method( )
removes the method from the receiver, but it
leaves inherited methods alone.
See below 2 simple example -
Example 1 using undef_method
class A
def x
puts "x from A class"
end
end
class B < A
def x
puts "x from B Class"
end
undef_method :x
end
obj = B.new
obj.x
result -
main.rb:15:in
': undefined methodx' for # (NoMethodError)
Example 2 using remove_method
class A
def x
puts "x from A class"
end
end
class B < A
def x
puts "x from B Class"
end
remove_method :x
end
obj = B.new
obj.x
Result -
$ruby main.rb
x from A class
I guess I can't comment on Adrian's answer because I don't have enough cred, but his answer helped me.
What I found: undef seems to completely remove the method from existence, while remove_method removes it from that class, but it will still be defined on superclasses or other modules that have been extened on this class, etc.
If you would like to remove method with name what calculate dinamically, you should use eigenclasses like:
class Foo
def self.bar
puts "bar"
end
end
name_of_method_to_remove = :bar
eigenclass = class << Foo; self; end
eigenclass.class_eval do
remove_method name_of_method_to_remove
end
this way is better than others answers, becouse here i used class_eval with block. As you now block see current namespace, so you could use your variables to remove methods dinamically
Object.send(:remove_const, :Foo)

Resources