How does 'defining a method' work semantically? - ruby

Background:
Here is what I understand about the object model (relative to my question below):
self always references the receiver in the current stack frame.
When you are in the top level and you say def someMethod the implicit receiver is self and you are creating a method which sits in the anonymous class associated with self. This anonymous class happens to sit just under Object (self is an instance of the Object class) so when you call someMethod, Ruby "takes a step to the right", and it lands in the anonymous class, thus finding and invoking your method.
This is similar to what goes on when you define methods inside of class definitions. If, when inside a class definition, you say: def self.classMethod you are creating a method in an anonymous class that sits just underneath the Class class. Methods of this class, existing "to the right" of the class currently being defined will not be visible to instances of the new class.
My Question:
How does "defining a method in a class" happen in the first place? (semantically)
Class objects aren't supposed to be different from normal objects, right?
From what I understand about message handling, Class objects have a table as a part of their state, presumable meaning it is an instance variable, that has the names of all of its instance methods. This is how the method look up works. (If Ruby doesn't find it , it goes up one and again, presumably the directions to the next link up the chain are a part of the state of the current Class object.)
Since Ruby doesn't really care about object type, I presume it doesn't care that it's looking in Class objects specifically when doing method look up. Rather, it's just following references and looking for bits of state with certain names. So, could I create my own "class objects" without using the class keyword that don't inherit from the Class class?
If that question doesn't make any sense, then I apologize. I just want to know what happens when the interpreter encounters the def keyword.

When you write 'def something' in ruby you are adding a method to a module. Sometimes that module is a 'class' (a type of module). It all depends on what 'self' is at the time:
class Foo
# right now self is 'Foo'
class << self
# right now self is 'Class:Foo'
end
def self.bar
# right now self is 'Foo'
end
end
def Foo.buz
# right now self is 'Foo'
end
obj = Foo.new
def obj.baz
# right now self is 'Foo:0x007fe8a632fa78' (an instance)
end
A class is just a type of module. Subclassing is one way of creating a pointer from One module up to another:
class Foo
end
class Bar < Foo
end
> Bar.ancestors
=> [Bar, Foo, Object, Kernel, BasicObject]
Another way is including mixins:
module Mixin
end
class Foo
include Mixin
end
> Foo.ancestors
=> [Foo, Mixin, Object, Kernel, BasicObject]
Method dispatch works on what exists in the inheritance chain. It's a list (not a tree) of parent modules and is ordered based on when the inheritance was created:
# bar.rb
module MixinA
def something
puts "MixinA"
super
end
end
module MixinB
def something
puts "MixinB"
end
end
class Base
def something
puts "Base"
super
end
end
class Sub < Base
include MixinB
include MixinA
def something
puts "Sub"
super
end
end
obj = Sub.new
obj.something
Run:
$ ruby bar.rb
Sub
MixinA
MixinB
Inspecting the chain:
> Sub.ancestors
=> [Sub, MixinA, MixinB, Base, Object, Kernel, BasicObject]
When a method call happens in walks this list looking for the method in question. If none of the modules in the chain have the method then the search starts over at the top but instead calls method_missing. In either case, the first resolution found wins.
Yehuda Katz wrote a good article on this stuff in 2009:
http://yehudakatz.com/2009/11/15/metaprogramming-in-ruby-its-all-about-the-self/

Related

"class<<self" vs "extend ClassMethods"

2 main techniques for creating class methods (without the obvious "def self.method") are:
Defining them in "class << self" block
Defining ClassMethod module and extending it later
I personally prefer second way, seems cleaner. Does anyone has any reason to prefer one technique over the other?
There's also "class_method" method, but I never used it, it has quite complex implementation and seem to do a lot more than previous 2.
self.method is the simplest option when you just need to create one method without dependencies or related logic.
class << self allows you to do far more than define methods on the metaclass. This is useful when you're defining methods which need to work with other parts of the metaclass (eg. aliasing existing method names).
For instance:
class Logger
class << self
attr_reader :payload
def log(message)
#payload = message
end
end
end
The module extension method comes in handy for method reuse and to group multiple coherent methods.
For instance:
module QueryMethods
def find
end
def where
end
end
module FactoryMethods
def build
end
def create
end
end
class BusinessModel
extend QueryMethods
extend FactoryMethods
end
First, the class << foo syntax opens up foo's singleton class (eigenclass). This allows you to specialise the behaviour of methods called on that specific object.
a = 'foo'
class << a
def inspect
'"bar"'
end
end
a.inspect # => "bar"
a = 'foo' # new object, new singleton class
a.inspect # => "foo"
class << self opens up self's singleton class, so that methods can be redefined for the current self object (which inside a class or module body is the class or module itself). Usually, this is used to define class/module ("static") methods
class << self is good at keeping all of your class methods in the same block. If methods are being added in def self.method from then there's no guarantee (other than convention and wishful thinking) that there won't be an extra class method tucked away later in the file.
def self.method is good at explicitly stating that a method is a class method, whereas with class << self you have to go and find the container yourself.
Which of these is more important to you is a subjective decision, and also depends on things like how many other people are working on the code and what their preferences are.
Pros of “class << self” style

Why can some classes and/or methods be called without instances of their parent class?

I'm near the finish of the Ruby track in Code Academy, and I'm curious about a peculiar thing: I was under the impression that a class is a repository of constants, methods, etc... and that in order to access most of them, you would first need to create an instance of that class or in some cases the methods of themselves can be invoked (as in they are all technically part of the global object). And then I saw something like this:
#Worked
Time.now
I understood as this as the method [now] of instance of class [Time] being invoked. I then tried to invoke the method on its own:
#Failed
now
and that failed, and I assumed that while a method can be created in the general scope [as part of the global object], if it relies on initialized variables of "parent" class, it cannot be called on its own, because it would not know which object to search for those initialized variables. Following that I created a test class:
class Clock
def initialize
#hours = 1
#minutes = 30
end
def showTime
puts "The time is: #{#hours}:#{#minutes}"
end
end
#this worked
watch = Clock.new
watch.showTime
#this failed
showTime
I then just created a basic method (assuming it's in the global level)
def mymethod
puts "The mighty METHOD!"
end
#Works
mymethod
and calling this method the way I did, without referencing the global object worked. So... the questions I have are as follows:
How can [Time.now] be called in this fashion? Shouldn't there be an instance of Time first created?
Why can't I call the method [now] on its own? Am I right that it relies on resources that it cannot find when called this way?
Why could I not call the method showTime on its own? But if I define any method on the "global" level I can access it without referencing the global object
First of all, your intuition is correct.
Every methods must be an instance method of some receiver.
Global methods are defined as private instance methods on Object class and hence seem to be globally available. Why? From any context Object is always in the class hierarchy of self and hence private methods on Object are always callable without receiver.
def fuuuuuuuuuuun
end
Object.private_methods.include?(:fuuuuuuuuuuun)
# => true
Class methods are defined as instance methods on the "singleton class" of their class instance. Every object in Ruby has two classes, a "singleton class" with instance methods just for that one single object and a "normal class" with method for all objects of that class. Classes are no different, they are objects of the Class class and may have singleton methods.
class A
class << self # the singleton class
def example
end
end
end
A.singleton_class.instance_methods.include?(:example)
# => true
Alternative ways of defining class methods are
class A
def self.example
end
end
# or
def A.example
end
Fun fact, you can define singleton methods on any object (not just on class objects) using the same syntax def (receiver).(method name) as follows
str = "hello"
def str.square_size
size * size
end
str.square_size
# => 25
"any other string".square_size
# => raises NoMethodError
Some programming language history — Singleton classes are taken from the Smalltalk language where they are called "metaclasses". Basically all object-oriented features in Ruby (as well as the functional-style enumerators on Enumerable) are taken from the Smalltalk language. Smalltalk was an early class-based object-oriented language created in the 70ies. It was also the language that invented graphical user interfaces like overlapping windows and menus et cetera. If you love Ruby maybe also take a look at Smalltalk, you might fall in love yet again.
This is known as a class method. If CodeAcademy didn't cover it, that's a shame. Here's some examples:
# basic way
class Foo
def self.bar; :ok; end
end
Foo.bar # => :ok
# alternate syntax
class Foo
class << self
def bar; :ok; end
end
end
# alternate syntax, if Foo class already exists
def Foo.bar; :ok; end
# alternate approach if Foo class already exists
Foo.class_exec do
def bar; :ok; end
end
# to define a class method on an anonymous 'class' for a single instance
# you won't need to use this often
Foo.new.singleton_class.class_exec do
def bar; :ok; end
end
# to define a class method on an instance's actual class
Foo.new.class.class_exec do
def bar; :ok; end
end
Another way to get class methods is to extend a module.
module FooMethods
def bar; :ok; end
end
module Foo
extend FooMethods
end
Foo.bar # => :ok
Note that with Modules, the methods are always defined as instance methods. This way they can be either extended into class scope or included into instance scope. Modules can also have class methods, using the exact same syntax / examples as shown above with classes. However there's not such as easy to load a module's class methods via include or extend.
How can [Time.now] be called in this fashion? Shouldn't there be an
instance of Time first created?
The Time.now method is a class method, not an instance method and therefore can be called directly on the Time class rather than an instance of it Time.new
Class methods are defined on the class themselves using the self keyword:
class Time
def self.now
# code
end
end
Time.now # works
Why can't I call the method [now] on its own? Am I right that it
relies on resources that it cannot find when called this way?
When you call a method "on its own" you're actually implicitly calling it on self:
self.now
The above is the same as just doing:
now
Why could I not call the method showTime on its own? But if I define
any method on the "global" level I can access it without referencing
the global object
You defined the showTime method on a specific class so you have to send that method to that class. When you define a method in the "global" scope you're implicitly defining it on self and the subsequent call to mymethod is actually self.mymethod so it will work.
Time.now is a class method.
To define a class method, you need to define the method with self. : def self.method_name
class Clock
#hours = 1
#minutes = 30
def self.showTime
puts "The time is: #{#hours}:#{#minutes}"
end
end
Clock.showTime
#=> The time is: 1:30
If you want to call now on its own, you can do so inside Time class :
class Time
puts now
#=> 2017-01-19 22:17:29 +0100
end

Class Methods in Object Class of Ruby

I was trying to implement my own attr_accessor method. I implemented that as follow.
class Object
def my_attr_accessor(*args) # self.my_attr_accessor(*args)
args.each do |arg|
define_method "#{arg}" do
return instance_variable_get("##{arg}")
end
define_method "#{arg}=" do |val|
instance_variable_set("##{arg}", val)
end
end
end
end
Then I created a class which calls the my_attr_accessor method.
class Runner
my_attr_accessor :name
end
test= Runner.new
test.name = "runner"
puts test.name
My question is even though I haven't explicitly defined self.my_attr_accessor method, it is acting as a class method. Can someone help me in figuring out how it's happening.
EDIT: Irrespective of making self.my_attr_accessor or my_attr_accessor in Object class, it works if I say my_attr_accessor within my Runner class. Why?
This is called "inheritance". In Ruby, subclasses "inherit" methods from their superclasses. In other words, if you send a message to an object, Ruby will look up a method whose name matches the message in the class of the object, and if it can't find it, it will follow that classes' superclass pointer, and then that classes' superclass pointer, and so on, until it either finds a matching method or reaches a class which doesn't have a superclass.
Since Class is a subclass of Object (indirectly via Module), it inherits Object's methods.
[Note: inheritance is a fundamental concept in Ruby, you should probably go back and learn the fundamentals of Ruby before trying advanced reflective metaprogramming. In particular how the ancestry chain (the superclass pointers) are constructed and message dispatch works.]
Since everything is an instance of Object in ruby, you can call your method from anywhere:
class Object
def my_attr_accessor(*args)
end
end
puts self.class # => Object
puts self.is_a?(Object) # => true
puts self.respond_to?(:my_attr_accessor) # => true
class Runner
puts self.class # => Class
puts self.is_a?(Object) # => true
puts self.respond_to?(:my_attr_accessor) # => true
my_attr_accessor :name
end
You create a new Runner with Runner.new. So you have an instance of the Runner class.
Since you called my_attr_accessor in your class block, you have created the method .name on your instance. This is important. my_attr_accessor is a call to the method my_attr_accessor. And in the base class, i.e. in Object, Ruby finds this method and calls it.
Now, you can call test.name = "runner".

What is the difference between `Class` and `class`

While creating a class, we use the keyword class like:
class Abc
Z = 5
def add
puts "anything here"
end
end
In console, Abc.class # => Class
How does Abc internally become a class? What is the difference between class and Class?
It would be great if anyone could explain how class constants and method are internally called, and if a method is not defined, then how we get the exception "undefined class method". What is the internal logic behind it?
There are three different things here:
class is a keyword, which is used to define or reopen a class
Object#class is a method, which returns the class of a given object
Class is the class which all classes are an instance of (including Class itself)
ndn's answer gives a nice overview of the different things "class" could refer to.
To answer your specific question:
How does Abc internally become a class?
Almost like any other object.
class Abc
end
is equivalent to:
Abc = Class.new do
end
It creates a new instance of Class and assigns it to the constant Abc.
To see what the different "class" things in Ruby mean, check out my other answer.
As for how methods are looked up:
There are multiple places a method can come from:
The class of the object
The parent of the class of the object
Modules, which are included/prepended
The singleton class of the object
The order of lookup is the following:
If it exists, the singleton class
Prepended modules
Methods defined in the class
Included modules
Recursively, the above rules for the parent class
There are a few things that have to be noted here:
If multiple modules are included/prepended, they will be looked up in the reverse order of how they were included/prepended
If a module was already included/prepended in one of the parrents, it won't be included/prepended again
If using these rules the method was not found til the very start of the hierarchy (BasicObject), the ancestor chain is searched again for a different method, called method_missing
BasicObject#method_missing is defined so that it throws a NoMethodError and that is where the error comes from
module M1
def foo
puts 'Defined in M1'
end
end
module M2
def foo
puts 'Defined in M2'
end
end
class C
include M1
prepend M2
def foo
puts 'Defined in C'
end
def method_missing(method_name)
puts 'Method missing' if method_name == :foo
end
end
c = C.new
# singleton method
def c.foo
puts "Defined in c's singleton"
end
puts c.singleton_class.ancestors
# => [#<Class:#<C:0xa2d0f8>>, M2, C, M1, Object, Kernel, BasicObject]
# ^ the singleton class,
# the prepended module,
# the C class itself,
# the included module,
# the rest of the hierarchy
# (Object is the implicit parent of all classes with no explicit parent)
with class Abc you define a class.
Abc.class is returning the Type, and the type of Abc is a Class
another example:
1337.class
=> Fixnum
"hi babe!".class
=> String
12.55.class
=> Float
(1..12).class
=> Range
so as you can see, each "datatype" is a class. in your case Abc is also a Datatype. And for the end of that chain, the class of a class is Class! :-)
Answering second par of the question, undefined class method happens when method you called is not present in such class - classes are just objects in Ruby, and as such they have their own set of methods. Ruby has several ways to define class methods, most common is probably
class Klass
def self.klass_method
...
end
end
the other is
class Klass
# some ordinary instance methods here
class << self
def klass_method
# this is class method
end
end
end
Some Rubyists prefer the latter, as it keeps all class methods in single block, but they are equivalent.

Help a ruby noob understand class inheritance

I'm trying to learn ruby by building a basic Campfire bot to screw around with at work. I've gotten pretty far (it works!) and learned a lot (it works!), but now I'm trying to make it a bit more complex by separating the actions to be performed out into their own classes, so that they can be easier to write / fix when broken. If you're interested in seeing all the (probably crappy) code, it's all up on GitHub. But for the sake of this question, I'll narrow the scope a bit.
Ideally, I would like to be able to create plugins easily, name them the same as the class name, and drop them into an "actions" directory in the root of the project, where they will be instantiated at runtime. I want the plugins themselves to be as simple as possible to write, so I want them all to inherit some basic methods and properties from an action class.
Here is action.rb as it currently exists:
module CampfireBot
class Action
#handlers = {}
def initialize(room)
#room = room
end
class << self
attr_reader :handlers
attr_reader :room
def hear(pattern, &action)
Action.handlers[pattern] = action
end
end
end
end
Where #room is the room object, and #handlers is a hash of patterns and blocks. I kind of don't understand why I have to do that class << self call, but that's the only way I could get the child plugin classes to see that hear method.
I then attempt to create a simple plugin like so (named Foo.rb):
class Foo < CampfireBot::Action
hear /foo/i do
#room.speak "bar"
end
end
I then have my plugins instantiated inside bot.rb like so:
def load_handlers(room)
actions = Dir.entries("#{BOT_ROOT}/actions").delete_if {|action| /^\./.match(action)}
action_classes = []
# load the source
actions.each do |action|
load "#{BOT_ROOT}/actions/#{action}"
action_classes.push(action.chomp(".rb"))
end
# and instantiate
action_classes.each do |action_class|
Kernel.const_get(action_class).new(room)
end
#handlers = Action.handlers
end
The blocks are then called inside room.rb when the pattern is matched by the following:
handlers.each do |pattern, action|
if pattern.match(msg)
action.call($~)
end
end
If I do puts #room inside the initialization of Action, I see the room object printed out in the console. And if I do puts "foo" inside Foo.rb's hear method, I see foo printed out on the console (so, the pattern match is working). But, I can't read that #room object from the parent class (it comes out as a nil object). So obviously I'm missing something about how this is supposed to be working.
Furthermore, if I do something to make the plugin a bit cleaner (for larger functions) and rewrite it like so:
class Foo < CampfireBot::Action
hear /foo/i do
say_bar
end
def say_bar
#room.speak "bar"
end
end
I get NoMethodError: undefined method 'say_bar' for Foo:Class.
The definition of hear can be pulled out of the class << self block and changed to:
def self.hear(pattern, &action)
Action.handlers[pattern] = action
end
to yield the exact same result. That also immediately explains the problem. hear Is a class method. say_bar is an instance method. You can't call an instance method from a class method, because there simply isn't an instance of the class available.
To understand the class << self bit, you'll have to do your own reading and experiments: I won't try to improve on what has already been said. I'll only say that within the class << self .. end block, self refers to the eigenclass or metaclass of the CampfireBot::Action class. This is the instance of the Class class that holds the definition of the CampfireBot::Action class.

Resources