RubyZG Feb meetup
Damir Svrtan
Has anyone seen puts?
1. Method lookup
2. Ancestor Chain
3. Eigenclass
4. Puts definition
5. Redefining puts
puts()/print()
Builtin function in Python and PHP
puts everywhere
puts 'Starting our program!'
class User
puts 'Defining the User class'
def initialize
puts 'Registering a new user'
end
end
But how?
Is it a special global method? NO
Down to basics
class User
def initialize(name)
@name = name
end
def name
@name
end
end
borko = User.new('Borko')
Ancestor chain
User.ancestors
=> [User, Object, Kernel, BasicObject]
class Student < User
end
Student.ancestors
=> [Student, User, Object, Kernel, BasicObject]
What's a superclass?
Student.superclass
=> User
User.superclass
=> Object
Object.superclass
=> BasicObject
BasicObject.superclass
=> nil
Ok, so where are borko's methods defined?
In it's class and all the ancestors of course!
one step to the right, then up!
Method lookup is done through the ancestor chain
again, one step to the right, then up!
What about the User class?
borko is an instance of the User class
User class is an instance of Class class
We can also define methods on the instance
Unlike other users, Borko can sing!
borko = User.new('Borko')
zdenko = User.new('Zdenko')
def borko.sing
puts "I'm singing in the rain!"
end
borko.sing
=> "I'm singing in the rain!"
zdenko.sing
=> undefined method `sing' for #<User:0x007fc8320bc528>
Eigenclass
The Eigenclass keeps all the singleton methods of an object
Hooks right into the ancestor chain
Does this syntax look familiar?
def borko.sing
puts "I'm singing in the rain!"
end
class User
def self.new_from_omniauth(email)
...
end
end
Ever done sumthin' like this?
class User
class << self # What is self?
# Defining the method on the eigenclass of self
def new_from_omniauth(email)
...
end
end
end
Or like this?
class User
class << self
def new_from_omniauth(email)
...
end
end
class << User
def new_from_omniauth(email)
...
end
end
def self.new_from_omniauth(email)
...
end
def User.new_from_omniauth(email)
...
end
end
class << User
def new_from_omniauth(email)
...
end
end
def User.new_from_omniauth(email)
...
end
Where is puts defined?
show-source borko.puts
From: io.c (C Method):
Owner: Kernel
Visibility: private
Number of lines: 8
static VALUE
rb_f_puts(int argc, VALUE *argv, VALUE recv)
{
if (recv == rb_stdout) {
return rb_io_puts(argc, argv, recv);
}
return rb_funcall2(rb_stdout, rb_intern("puts"), argc, argv);
}
borko.class.ancestors.include? Kernel
=> true
pry & pry-doc
Back to square one
puts 'Starting our program!'
class User
puts 'Defining the User class'
def initialize
puts 'Registering a new user'
end
end
User
#<User:0x007f987>
main
Console main
self
=> main
self.class
=> Object
self.class.ancestors.include? Kernel
=> true
self.class.private_instance_methods.include? :puts
=> true
self.private_methods.include? :puts
=> true
class User
end
User.class
=> Class
User.class.ancestors.include? Kernel
=> true
User.class.private_instance_methods.include? :puts
=> true
borko = User.new
borko.class
=> User
borko.class.ancestors.include? Kernel
=> true
borko.class.private_instance_methods.include? :puts
=> true
Why don't we redefine puts?
puts 'Ruby is fun!'
=>
_________________________
( Ruby is fun! )
-------------------------
o ^__^
o (oo)\_______
(__)\ )\/\/
||----w |
|| ||
Cow says mooooo!
class Cow
def moo
puts 'mooooooo'
end
end
milka = Cow.new
def milka.puts(text)
cow_output =
"_________________________\n"\
"( #{text} )\n"\
"-------------------------\n"\
" o ^__^\n"\
" o (oo)\_______\n"\
" (__)\ )\/\/\n"\
" ||----w |\n"\
" || ||\n"
super(cow_output)
end
On the eigenclass!
> show-source milka.puts
From: user.rb @ line 49:
Owner: #<Class:#<Cow:0x007fbc409ef940>>
Visibility: public
Number of lines: 13
def milka.puts(text)
cow_output =
"_________________________\n"\
"( #{text} )\n"\
"-------------------------\n"\
" o ^__^\n"\
" o (oo)\_______\n"\
" (__)\ )\/\/\n"\
" ||----w |\n"\
" || ||\n"
super(cow_output)
end
> milka.moo
=>
_________________________
( mooooooo )
-------------------------
o ^__^
o (oo)_______
(__) )//
||----w |
|| ||
class Cow
def puts(text)
cow_output =
"_________________________\n"\
"( #{text} )\n"\
"-------------------------\n"\
" o ^__^\n"\
" o (oo)\_______\n"\
" (__)\ )\/\/\n"\
" ||----w |\n"\
" || ||\n"
super(cow_output)
end
end
On every cow!
show-source Cow#puts
From: (pry) @ line 3:
Owner: Cow
Visibility: public
Number of lines: 13
def puts(text)
cow_output =
"_________________________\n"\
"( #{text} )\n"\
"-------------------------\n"\
" o ^__^\n"\
" o (oo)\_______\n"\
" (__)\ )\/\/\n"\
" ||----w |\n"\
" || ||\n"
super(cow_output)
end
> Cow.new.moo
=>
_________________________
( mooooooo )
-------------------------
o ^__^
o (oo)_______
(__) )//
||----w |
|| ||
class Object
def puts(text)
cow_output =
"_________________________\n"\
"( #{text} )\n"\
"-------------------------\n"\
" o ^__^\n"\
" o (oo)\_______\n"\
" (__)\ )\/\/\n"\
" ||----w |\n"\
" || ||\n"
super(cow_output)
end
end
Everybody say moooo!
puts 'moooooooo'
class User
puts 'moooooooo'
def initialize
puts 'moooooooo'
end
end
User.new
_________________________
( mooooooo )
-------------------------
o ^__^
o (oo)_______
(__) )//
||----w |
|| ||
_________________________
( mooooooo )
-------------------------
o ^__^
o (oo)_______
(__) )//
||----w |
|| ||
_________________________
( mooooooo )
-------------------------
o ^__^
o (oo)_______
(__) )//
||----w |
|| ||
Redefine rampage
- raise
- backticks ``
- private/protected/public
- eval
- require
Fin.
madebydna.com/all/code/2011/06/24/eigenclasses-demystified.html
and visit:
Read:
Methods you thought were keywords
By Damir Svrtan
Methods you thought were keywords
- 1,206