Created
February 24, 2018 17:02
-
-
Save haroldrandom/d53f76d16b6908b2b9f216ac48daef02 to your computer and use it in GitHub Desktop.
Difference between instance_eval and class_eval
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
# encoding: UTF-8 | |
class RackServer | |
def options | |
#puts "RackServer: #{self} #{__LINE__}" | |
@options ||= parse_options(ARGV) | |
end | |
def start | |
p options | |
end | |
private | |
def parse_options(args) | |
#puts "RackServer: #{self} #{__LINE__}" | |
options = default_options | |
options | |
end | |
def default_options | |
#puts "RackServer: #{self} #{__LINE__}" | |
{ | |
:environment => 'development', | |
:pid => nil, | |
:config =>'config.ru' | |
} | |
end | |
end | |
class RailsServer < RackServer | |
def default_options | |
#puts "RailsServer: #{self} #{__LINE__}" | |
super.merge({ | |
:config => File.expand_path(__FILE__) | |
}) | |
end | |
def start | |
super | |
end | |
def demo_show | |
'rails class demo show' | |
end | |
def config | |
@config ||= {} | |
end | |
puts "#{__LINE__}, #{self}" # class | |
class << self | |
def instance | |
@instance ||= new | |
end | |
def configure(&blk) | |
instance.configure(&blk) | |
end | |
end | |
def configure(&blk) | |
puts "#{__LINE__}, #{self}" # instance | |
instance_eval(&blk) | |
#instance_eval do | |
# puts "#{__LINE__}, #{self}" # instance, same as line 61 | |
# # implicitly means that demo_show get invoked by an instance of RailsServer | |
# p demo_show | |
# blk.call() if block_given? | |
#end | |
end | |
end | |
RailsServer.class_eval do | |
# bar is defined within the context of class RailsServer | |
# So, bar become a instance method | |
def bar | |
puts "#{__LINE__}, #{self} call bar by class_eval" | |
end | |
end | |
RailsServer.instance_eval do | |
# instance_eval invoked like this way will open the singleton class of RailsServer, called #RailsServer. | |
# Because RailsServer has to be someone's instance, instance_eval can finally be worthy of the name. | |
# So #RailsServer get created. | |
# That's an unconsipicuous difference between instance_eval and class_eval, | |
# if there is no singleton class of current instance, instance_eval will create one for it, but class_eval don't | |
# | |
# You can do this by doing | |
# class << self | |
# ... | |
# end | |
# within the class definition. | |
# Actually, Module#extend works like that. | |
def bar | |
# bar is defined witin the context of class #RailsServer (metaclass of RailsServer), | |
# So, bar become a class method | |
# Note that, class method is nothing but a singleton method of a class, which is #RailsServer in this case | |
# An instance method of a singleton class | |
puts "#{__LINE__}, #{self} call bar by instance_eval" | |
end | |
end | |
server = RailsServer.new | |
server.start | |
server.bar | |
RailsServer.bar | |
puts "#{__LINE__}, #{server} within ousider" # instance | |
# Demo | |
RailsServer.configure do | |
puts "Start to RailsServer.configure...config: #{config}" | |
config[:r] = 'Ruby' | |
config[:p] = 'Python' | |
config[:c] = 'C++' | |
config[:g] = 'golang' | |
puts "After to RailsServer.configure...config: #{config}" | |
end | |
# instance_eval invoked like this way will also open the singleton class of server instance, | |
# which is the metaclass of server instance, called #server | |
#server.instance_eval do | |
# puts "#{__LINE__}, #{self}" | |
#end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment