As the responsibility of our applications grows, so too does our code. We'll walk through techniques of object-oriented programming that help clarify our intent and put responsibilities right where we need them.
source.extend(Source), destination, amount end def execute source.transfer end module Source def transfer self.balance -= amount destination.balance += amount end end end Saturday, June 1, 13
source.extend(Source), destination, amount end def execute source.transfer end module Source def transfer self.balance -= amount destination.balance += amount end end end Saturday, June 1, 13
source.extend(Source), destination, amount end def execute source.transfer end module Source def transfer self.balance -= amount destination.balance += amount end end end source.extend(Source) Saturday, June 1, 13
module Greeting def hello_world “Hello, from #{@name}” end end user.delegate(:hello_world, Greeting) #=> “Hello, from @saturnflyer” user.hello_world #=> NoMethodError Saturday, June 1, 13
module Greeting def hello_world “Hello, from #{self.name}” end end user.delegate(:hello_world, Greeting) #=> “Hello, from @saturnflyer” user.hello_world #=> NoMethodError Saturday, June 1, 13
module Greeting def hello_world “Hello, from #{self}” end end user.delegate(:hello_world, Greeting) #=> “Hello, from #<User:0x007f8d4b02d9 user.hello_world #=> NoMethodError Saturday, June 1, 13
=> Greeting) do user.hello_world #=> “Hello, from @saturnflyer” Casting.delegating(user => FormalGreeting) do user.hello_world #=> “Good day to you! from @saturnflyer” end end user.hello_world #=> NoMethodError Saturday, June 1, 13
source.extend(Source), destination, amount end def execute source.transfer end module Source def transfer self.balance -= amount destination.balance += amount end end private_constant :Source end Saturday, June 1, 13
do |m| undef_method m end end include kernel def self.const_missing(n) ::Object.const_get(n) end def initialize(obj) __setobj__(obj) Saturday, June 1, 13
self.__getobj__ begin target.respond_to?(m) ? target.__send__(m, *args, &block) : super(m, *args, &b ensure [email protected]_if {|t| %r"\A#{Regexp.quote(__FILE__)}:#{__LINE__-2}:"o =~ t} if $@ end end def respond_to_missing?(m, include_private) r = self.__getobj__.respond_to?(m, include_private) if r && include_private && !self.__getobj__.respond_to?(m, false) warn "#{caller(3)[0]}: delegator does not forward private method \##{m}" return false end Saturday, June 1, 13
include_private) if r && include_private && !self.__getobj__.respond_to?(m, false) warn "#{caller(3)[0]}: delegator does not forward private method \##{m}" return false end r end def methods(all=true) __getobj__.methods(all) | super end def public_methods(all=true) Saturday, June 1, 13
def public_methods(all=true) __getobj__.public_methods(all) | super end def protected_methods(all=true) __getobj__.protected_methods(all) | super end def ==(obj) return true if obj.equal?(self) Saturday, June 1, 13
= data if version == :__v2__ vars.each_with_index{|var, i| instance_variable_set(var, values[i])} __setobj__(obj) else __setobj__(data) end end def initialize_clone(obj) self.__setobj__(obj.__getobj__.clone) end def initialize_dup(obj) self.__setobj__(obj.__getobj__.dup) Saturday, June 1, 13
self.__setobj__(obj.__getobj__.dup) end private :initialize_clone, :initialize_dup [:trust, :untrust, :taint, :untaint, :freeze].each do |method| define_method method do __getobj__.send(method) super() end end Saturday, June 1, 13
|method| define_method method do __getobj__.send(method) super() end end @delegator_api = self.public_instance_methods def self.public_api @delegator_api end end Saturday, June 1, 13