When sent a message, a Ruby object searches to see whether it has a method by that name to respond with. Its method lookup searches in the following order, and uses the first method it finds.
Singleton methods defined on itself (aka methods on its "eigenclass")
Methods defined in its class
Any modules mixed into its class, in reverse order of inclusion (only the earliest inclusion of a given module has any effect - if the superclass includes module A, and the subclass includes it again, it’s ignored in the subclass; if the subclass includes A then B then A, the second A is ignored) (update: note that this was written before Module.prepend existed)
Its parent class
Any methods mixed into the parent class, the parent's parent, etc.
Or, to put it more simply, it looks on itself, then everything in self.class.ancestors in the order they're listed.
This lookup path is followed at the moment the method is called; if you make an instance of a class, then reopen the class and add a method or mix one in via a module, the existing instance will gain access to that method.
If all of this fails, it looks to see if it has a method_missing method, or if its class does, its parent class, etc.
My question is this: aside from examining the code by hand, or using example methods like puts "I'm on module A!", can you tell where a given method came from? Can you, for example, list an object's methods and see "this one is on the parent class, this one is on module A, this one is on the class and overrides the parent class," etc?
Object#method returns a Method object giving meta-data about a given method. For example:
> [].method(:length).inspect
=> "#<Method: Array#length>"
> [].method(:max).inspect
=> "#<Method: Array(Enumerable)#max>"
In Ruby 1.8.7 and later, you can use Method#owner to determine the class or module that defined the method.
To get a list of all the methods with the name of the class or module where they are defined you could do something like the following:
obj.methods.collect {|m| "#{m} defined by #{obj.method(m).owner}"}
Get the appropriate Method (or UnboundMethod) object and ask for its owner. So you could do method(:puts).owner and get Kernel.
To find which instance methods are defined on A (but not on superclasses):
A.instance_methods(false)
To find which instance methods are defined on A AND its superclasses:
A.instance_methods
To find which class (or module) a given method is defined on:
method(:my_method).owner
To find which object is the receiver for a given method:
method(:my_method).receiver
You can use Object#method. For example,
[1, 2, 3].method(:each_cons) # => #<Method: Array(Enumerable)#each_cons>
tells that the each_cons method of an Array comes from the Enumerable module.
Related
So, from what I understand, in a class, a self.method is like a class method, whereas a regular method is like an instance method. But, as you can't instantiate a module, why would I use one over the other? What is the difference between these two in a module?
So, from what I understand, in a class, a self.method is like a class method, whereas a regular method is like an instance method.
That is not true. Ruby only has one single kind of method: instance methods. So, what you call a "regular method" is not "like" an instance method, it is an instance method. And there are no class methods in Ruby, every method is an instance method.
There are two ways to define a method in Ruby: with an explicit definee (def foo.bar) and without (def bar, which is then using the default definee).
In the first case, it is easy to know where a method will be defined: if you say def foo.bar, the method will become an instance method of foo's singleton class, always.
If you say def bar, the method becomes an instance method of the default definee, which usually, but not always, is the closest lexically enclosing module definition body. The most notable exception is a method that is defined directly in a script body, in this case, there is no lexically enclosing module definition, and the default definee is Object instead. In fact, there is even another twist: the method will be implicitly defined as private as well.
So, in your case, the first method will become an instance method of the singleton class of self (and inside a module definition body, self is the module itself), the second method will become an instance method of the module.
But, as you can't instantiate a module,
Ruby has a feature called inheritance. While it is true that you can directly instantiate a module, you can instantiate a class that inherits from a module. In fact, since the Object class inherits from the Kernel module (which has instance methods like Kernel#puts or Kernel#require, which may have used once or twice), and almost every class directly or indirectly inherits from Object, it is highly likely that you will have in your Ruby programming already have instantiated an indirect instance of a module and used a module's instance methods.
Enumerable is another important module in Ruby that contains methods like map, select, etc. that both Array and Hash inherit from.
why would I use one over the other?
There's really not much to it: you'd use an instance method, if you want to … well use an instance method, i.e. want to have a method that has privileged access to the internal representation of self across many different instances of the same module.
You would use a method of the singleton class, if you want the method to be only available for that single object.
There is one and only one reason for having module methods: to invoke those methods on the module in which they defined (using self: def self.my_method...). An example of this is Ruby's built-in Math module. All methods in this module are module methods. These methods are all invoked with Math as their explicit receiver (e.g., Math.sqrt(2.5)). In effect, they are used like functions in non-OO languages.
When you include, prepend or extend a module from a class, any module methods are simply ignored.
You might find this (timely) article helpful in understanding the Ruby object model and how methods are “looked up”: https://www.honeybadger.io/blog/ruby-method-lookup/
I've read stackoverflow posts on this topic as well as several articles which include A Primer on Ruby Method Lookup, What is the method lookup path in Ruby. In addition, I checked out the object model chapter in Ruby Metaprogramming 2, asked in a few chat rooms, and made this reddit thread. Short of learning C, I've done what I can to figure this out.
As described by the resources above, these 6 places are checked (in order) during method lookup on a receiving object like fido_instance:
singleton class of fido_instance
IClass (from an extended module)
IClass (from a prepended module)
class
IClass (from an included module)
superclass (if method isn't found here, repeat steps 4-6)
Obviously, the diagram is incomplete, and all of these singleton classes might not have been created in the real world. Still, those 6 steps leave a lot to be desired, and don't cover the following scenario. If there were no extended/prepended IClass above the singleton class of fido_instance, then there's no explanation of whether step 4 is executed on the singleton class of fido_instance. I have to assume not since the whole method lookup would short circuit.
If I were to guess a set of steps that could explain ruby's method lookup behavior, it might look like:
check fido_instance.class for the method. (obviously, ruby isn't going to use its own #class method to do the method lookup, but it conveys the logic of the process)
check fido_instance.class.superclass for the method. Keep adding .superclass and checking for the method until no superclasses are left. (again, ruby isn't going to use its own #superclass method)
method wasn't found. Start at step 1, looking for #method_missing this time.
I also recall reading that there's a separate method lookup process if the receiving object is a class, but I can't recall where.
So what's the correct, detailed explanation that doesn't involve knowing C?
There's a ... gem ... in that second ref that I think gets to the core of the answer: ancestors of the singleton class. Applied to your object, it would be:
fido_instance.singleton_class.ancestors
This will always give you the order of method lookup that Ruby uses. It's pretty simple when you view it this way, and that's the bottom line answer to your question. Ruby will start at the singleton_class and work its way up the ancestors looking for that method. Using your diagram:
fido.singleton_class.ancestors
=> [Fetch, WagTail, DogClass, Object, Kernel, BasicObject]
(Note1: Bark is not part of this output because you used extend instead of include. More on this in a second.)
(Note2: If it doesn't find it all the way up to BasicObject, then it will call method_missing up the same ancestry chain.)
It's no different when calling a method on a class, because in Ruby a class it just an instance of class Class. So DogClass.method1 will search for method1 on DogClass.singleton_class and then up its ancestry chain, just like before.
DogClass.singleton_class.ancestors
=> [Bark, Class, Module, Object, Kernel, BasicObject]
Since you used extend for Bark, this is where we find it! So if Bark defined a method bark, then you can call DogClass.bark because that method is defined in DogClass's singleton_class' ancestors.
To understand what that ancestry tree will be (instead of relying on printing it out every time), you simply need to know how the ancestry is modified by subclassing, extend, include, prepend, etc.
Subclassing gives the child class the entire ancestry chain of its superclass.
includeing a module in a class C adds that module into the ancestry chain after C and before everything else.
prepending a module in a class C adds that module into the ancestry chain before everything, including C and any currently prepended modules.
def x.method1 adds method1 to x.singleton_class. Similarly x.extend(M) will add M to the ancestry of x.singleton_class (but not to x.class). Note that the latter is exactly what happened with Bark and DogClass.singleton_class, but can equally apply to any object.
Leaving out extend from the above list because it does not modify the object's ancestry chain. It does modify the ancestry of that object's singleton_class -- as we saw, Bark was included in DogClass.singleton_class.ancestors.
Tangent:
The bit about class methods above is the key to me for understanding how important singleton classes are to Ruby. You obviously can't define bark on DogClass.class, because DogClass.class == Class and we don't want bark on Class! So how can we allow DogClass to be an instance of Class, allowing it to have a (class) method bark that is defined for DogClass but not unrelated classes? Using the singleton class! In this way, defining a "class method", like by def self.x inside class C, is sort of like C.singleton_class.send(:define_method, :x) {...}.
The quiz problem:
Which of the following statements about classes in Ruby are true?
Array is an instance of Class.
When self is used within the definition of an instance method, it refers to the current instance of the class.
Ruby supports multiple inheritance.
Public methods of a class cannot be redefined after an instance of that class is instantiated.
More than one answer could be correct.
I know that (3) is incorrect because Ruby does not support multiple inheritance. I chose (1) but got the question wrong. Are other statements about the classes in Ruby also true?
TL;DR
#1 and #2 are both correct answers. You already know that Ruby doesn't support multiple inheritance, although it does support module mixins. So, 3 and 4 are false, while 1 and 2 are true; see below for details.
Array.is_a? Class
First of all, Array is a class, but doesn't inherit from Class or have Class in its ancestry. Consider:
Array.is_a? Class
# => true
Array.ancestors
# => [Array, Enumerable, Object, PP::ObjectMixin, Kernel, BasicObject]
Array < Class
# => nil
On the other hand, as #Priti correctly points out in his comment below, Array is an instance of Class:
Array.instance_of? Class
# => true
So, while Array doesn't inherit from Class in its ancestry chain, it is (strictly speaking) an instance of a Class. That makes #1 technically correct.
Object#self
The self method is actually a bit more complex than one might expect. Ruby 1.9 defines it this way:
self is the "current object" and the default receiver of messages (method calls) for which no explicit receiver is specified. Which object plays the role of self depends on the context.
In a method, the object on which the method was called is self
In a class or module definition (but outside of any method definition contained therein), self is the class or module object being defined.
In a code block associated with a call to class_eval (aka module_eval), self is the class (or module) on which the method was called.
In a block associated with a call to instance_eval or instance_exec, self is the object on which the method was called.
So, #2 is correct, but only tells part of the story.
Open Classes
Ruby supports open classes (see Classes are Open), so you can redefine instance and class methods at run-time. So, #4 is wrong.
While all other answers are explaining each options,but I think Array is an instance of Class. is true.Object#instance_of? says: Returns true if obj is an instance of the given class. See also Object#kind_of?.
Array.instance_of? Class # => true
2 is also correct. Self works like this in many languages.
http://ruby-doc.org/docs/keywords/1.9/Object.html
1, 2, and 3 are true. Array is an instance of Class, self is always the receiver, and Ruby does support multiple mixin inheritance. 4 is false, methods can be added, removed, and modified at any point in time.
I'm reading 'metaprogramming in ruby'
its such an EXCELLENT book. Seriously, it talks about stuff that I never hear mentioned elsewhere.
I have a few specific questions however about objects (I'm in the first few chapters)
I understand that the RubyGems gem installs the method 'gem' to the module Kernel so that it shows up on every object. Is there a reason they didnt put it into the Object class?
He talks about how when ruby looks for the method it always goes right then up. What exactly does 'up' mean? I see it in the diagram, its just that I dont really understand the purpose of 'up'. he doesnt explain that part much.
What is the point of the Object class? How come those methods cant be just placed into Class? If every object belongs to a class (even if its Class), then what is the point of object, basicobject, and kernel?
String, Array, blah blah are obviously an instance of Class. Class is also an instance of itself. So if Class is an instance of Class.... how does it also inherit from Object? Where in the code does it relates to BOTH Class and Object?
I know kernel contains methods such as puts that can be used everywhere, and this relates to question 1, but why cant they just condense it and put it all into Object... where it would seem everything inherits from object anyway
Both would work, but typically methods on Object should only be methods that deal with a particular object. Puting things in the Kernel module are less about about object and more global.
I assume it means "up the inheritance chain". So it looks for the method on the child class, then on that classes parent class until it finds one or runs out of parent classes.
Object is the base class of all objects, naturally (For ruby 1.8 at least). The crazy part is that a class is actually an instance of the Class class. (you follow that?) So adding instance methods to Class would add methods to class objects, but not instances of those classes.
Nearly everything in ruby is an object. Class.superclass is actually Module (which is like a class you can't instantiate) and Module.superclass returns Object. So Class < Module < Object is the inheritance chain if the Class class. (For ruby 1.8 at least)
More convention than anything. Since Object can get rather HUGE, it's customary to put things into modules and then combine those modules later. If the method doesn't deal with an instance of an object directly as self then the method doesn't belong directly in Object. More global non-object instance methods like gem go in the Kernel module to signify that they are simply methods available everywhere.
Some more about class objects and inheritance...
class Foo < Bar
def hi
puts 'Hi!'
end
end
What this does is really quite awesome. It defines a class object, of course. Now this class object is configured to have a name Foo, a parent class Bar and a method hi. This info is sort of like this class object's meta data.
Now the class object Foo itself is an instance of Class. But Foo defines a class that inherits from Bar. The Class class defines a data structure to store this meta data about a class.
You can think of the Class class sorta kinda being defined like this:
class Class < Module
# fictional method called on class creation
def set_meta_data(name, superclass, methods)
#name = name
#superclass = superclass
#methods = methods
end
# fictional way in which an instance might be created
def new
instance = Object.new
instance.superclass = #superclass
instance.addMethods(#methods)
instance
end
end
So a class object itself would inherit from Class but it would create objects that do not.
Thinking of classes as objects can be a bit mind bending in this way, but this also why ruby is awesome.
For 1 and 5, pseudo-keyword commands tend to go into Kernel rather than Object.
For 2, it makes sense for sub-classes to be "down" relative to their parent class (sub literally meaning "beneath"). Therefore if you're heading for a parent class and its ancestors, you have to go "up".
For 3, an object object is not an instance of Class, it is an instance of Object.
For 4, what's wrong with something being an instance of Class and inheriting from Object? All classes inherit from Object.
I am wondering if there is a Ruby method call that shows only the methods defined by the Ruby object it's called from, as opposed to all the methods defined by its ancestor classes, which is what methods seems to do.
methods takes an optional boolean parameter, which specifies whether to also list the methods from the object's class and its superclasses or just the object's singleton methods. So you can do obj.methods(false) to only get the singleton methods defined on obj.
If you want the methods defined by the object's class, but not those defined by its superclasses, you can get that by calling instance_methods(false) on the object's class, so it's obj.class.instance_methods(false).
I'm partial to obj.methods.sort but some of the other answers are better in certain cases as they describe
You can also use obj.methods.sort.grep /foo/ to find method names matching the regexp.
This is helpful when you have an idea of what you're looking for.
You have a few options - object.methods, object.public_methods, object.singleton_methods... it depends on what you want. Since they both return an array, you might want to try something like:
# obj is the current object
parent = obj.class.superclass
methods = (obj.methods - parent.methods)