Create a class with no instance methods in Ruby - ruby

How can I create a class with no instance methods defined? Not even __send__ or __id__.

You can use Module#undef_method to undefine methods:
class Foo < BasicObject
instance_methods.each { |method| undef_method(method) }
end
Foo.instance_methods #=> []
foo = Foo.new
foo.__id__ #=> NoMethodError: undefined method `__id__' for #<Foo:0x007fb9da565dd8>
foo.__send__(:test) #=> NoMethodError: undefined method `__send__' for #<Foo:0x007fb9da565dd8>
In this example Foo inherits from BasicObject, because this class itself has very few instance methods defined and thus, undefining them is faster. This is not obligatory, meaning, that you can undefine instance methods from any class no matter what it inherits from, so it could be very well written as:
class Foo
instance_methods.each { |method| undef_method(method) }
end

Related

instance_eval's behaviour inside a instance method

Below is my snippet which i tried,
class Person
def test(arg)
self.class.instance_eval do
define_method(arg) {puts "this is a class method"}
end
end
end
irb(main):005:0> Person.new.test("foo")
=> #<Proc:0x9270b60#/home/kranthi/Desktop/method_check.rb:4 (lambda)>
irb(main):003:0> Person.foo
NoMethodError: undefined method `foo' for Person:Class
irb(main):007:0> Person.new.foo
this is a class method
=> nil
Here am adding a method to the Person class dynamically using instance_eval and define_method. But why is this behaving as instance method?.
Is that completely dependent on self?
Confused. Can anyone explain me or a reference link also appreciated.
It's because define_method defines instance method of the receiver. Your receiver (self) is Person class, so it defines instance method of Person class. You can achieve what you want accessing to Person's metaclass:
def test(arg)
class << self.class
define_method(arg) { puts 'this is a class method' }
end
end
I haven't tested it, but it should work.

Where does `singleton` methods reside in Ruby?

I was playing with singleton class in my IRB. And doing so tried the below snippets.
class Foo ; end
#=> nil
foo = Foo.new
#=> #<Foo:0x2022738>
foo.define_singleton_method(:bar , method(:puts))
#=> #<Method: Object(Kernel)#puts>
Here above I just created a singleton method on instance of class Foo.
foo.bar("hi")
hi
#=> nil
foo.singleton_methods
#=> [:bar]
foo_sing = foo.singleton_class
#=> #<Class:#<Foo:0x2022738
foo_sing.is_a? Class
#=> true
foo_sing.instance_of? Class
#=> true
foo_sing.inspect
#=> "#<Class:#<Foo:0x1e06dc8>>"
In the above I tried to create a singleton class on instance of class Foo. And also tested if foo_sing holds reference to the singleton class on instance of class Foo.
foo_sing.methods(false)
#=> []
foo_sing.methods.include? :bar
#=> false
In the above I was looking if singleton_method bar is in the foo_sing or not.But found it is not present there.Then my question is - where does thosesingleton_method reside in Ruby?
foo_sing.new.methods(false)
#TypeError: can't create instance of singleton class
# from (irb):10:in `new'
# from (irb):10
# from C:/Ruby193/bin/irb:12:in `<main>'
class Bas < foo_sing ; end
#TypeError: can't make subclass of singleton class
# from (irb):16
# from C:/Ruby193/bin/irb:12:in `<main>'
In the above part I was checking if we can create,instance of singleton class or not and subclass of singleton class,like regular class. But the answers I found as NO. What is the concept or theory or purpose behind it ?
Again in the following code I can see the that same name methods are being overridden inside a singleton class. But when I am searching that method inside the class not found as I asked above.
class Foo ; end
#=> nil
foo = Foo.new
#=> #<Foo:0x225e3a0>
def foo.show ; puts "hi" ; end
#=> nil
foo.show
#hi
#=> nil
class << foo ;def show ; puts "hello" ; end ;end
#=> nil
foo.show
#hello
#=> nil
You're on the right track.
1) When looking for the method in the singleton class, you wanted to use instance_methods, not methods:
foo_sing.instance_methods.include? :bar # => true
# or
foo_sing.method_defined? :bar # => true
It is a bit confusing, since method_defined? really means "instance methods defined?", while methods really means singleton methods...
2) You can't subclass or instantiate a singleton class because it is meant to be a singleton, i.e. have exactly one instance.
It doesn't matter anyways, since you should instead use mixins for code that you want to reuse. These can be included/prepended in as many singleton classes or normal classes as you want:
foo.extend ResuableFunctionality
# or equivalently:
class << foo
include ReusableFunctionality
end

dynamically defining instance methods but not class methods

Ruby 1.9.3: I am trying to implement a method which takes as argument a class, a symbol and a proc and defines (eventually overwriting) a new instance method for that class, but not a class method so that this test should pass:
require 'test/unit'
include Test::Unit::Assertions
class String
def my_method
'my_method'
end
end
def define_instance_method(klass, method, &block)
# klass.send :define_method, method, &block
# ...
end
define_instance_method(Object, :my_method) { 'define_instance_method my_method' }
define_instance_method(String, :my_method) { 'define_instance_method my_method' }
assert Object.new.my_method == 'define_instance_method my_method'
assert_raise(NoMethodError) { Object.my_method }
assert String.new.my_method == 'define_instance_method my_method'
assert_raise(NoMethodError) { String.my_method }
I did many tryings (define_method, define_singleton_method, class_eval, instance_eval, instance_exec, module_eval...) but with no success; do you have any ideas?
#ProGNOMmers, recall that objects in Ruby are classes and classes are objects.
So everything in Ruby are objects, even classes :)
And when you define a method inside Object it will also be available to Class as well as to any class that inherits from Object.
That's mean to all classes.
Some proof:
define_instance_method(String, :my_method) { 'define_instance_method my_method' }
p String.new.my_method
p String.my_method
# => "define_instance_method my_method"
# => stackoverflow.rb:11:in `<main>': undefined method `my_method' for String:Class (NoMethodError)
See, your method not yet defined inside Object, thus not available inside String.
Now let's do it:
define_instance_method(Object, :my_method) { 'define_instance_method my_method' }
p String.my_method
# => "define_instance_method my_method"
p Array.my_method
# => "define_instance_method my_method"
p NilClass.my_method
# => "define_instance_method my_method"
So just comment define_instance_method(Object... in your tests
and String specs will pass just well.
Here are some crash tests
class_eval should work for you. Let me know why it isn't working for you
class A
end
A.class_eval do
define_method(:foo) {puts 'hello'}
end
A.new.foo #hello
A.foo #NoMethodError: undefined method `foo' for A:Class

Ruby Class Methods vs. Methods in Eigenclasses

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.

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