CSC/ECE 517 Fall 2007/wiki1b 2 22: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
Line 77: Line 77:
= Advantages =
= Advantages =
#Allow you to catch problem at runtime.
#Allow you to catch problem at runtime.
#Allow you define a generic method_missing and handle any undefined method.
#Allow you define a generic method_missing and handle any undefined method.  This is a big advantage over Java.  In Java, when you call method is not define, the program will not compile.
#The use of method_missing falls under the general technique of metaprogramming.
#The use of method_missing falls under the general technique of metaprogramming.  You can employ metaprogramming in missing_function to write a another function to handle the call.


= References =
= References =

Revision as of 01:46, 5 October 2007

Introduction - method_missing

The method_missing is a method that called whenever someone tries to call a method in your object that doesn't exist. It is a Ruby kernel method. It used as a method of last resort. When you send a message to a Ruby object, Ruby looks for a method to invoke with the same name as the message you sent. First it looks in the current self object’s own instance methods. Then it looks in the list of instance methods that all objects of that class share, and then in each of the included modules of that class, in reverse order of inclusion. Then it looks in that class’s superclass, and then in the superclass’s included modules, all the way up until it reaches the class Object. If it still can’t find a method, the very last place it looks is in the Kernel module, included in the class Object. [1]

Examples

1. Object composition

class SimpleCallLogger
 def initialize(o)
   @obj = o
 end
 def method_missing(methodname, *args)
   puts "called: #{methodname}(#{args})"
   a = @obj.send(methodname, *args)
   puts "\t-> returned: #{a}"
   return a
 end
end

This object "intercepts" all method calls made to it, prints out a message and forwards on the method call to an internal object using the 'send' method, without knowing anything about the object passed to it. It can be used to debug some code without littering it with print statements. [2]


2. Factorial

Let's create a Computer class that contains a factorial method (you know the famous n! thing).

class Computer
 def factorial n
     raise ArgumentError if n < 0
     f = 1
     n.downto(1) do |i|
       f = f * i
     end
     f
   end
 end
 computer = Computer.new
 puts computer.factorial(4)

We would like to use some notation close to the usual notation:

computer = Computer.new
puts computer._4!

Obviously, we cannot create methods for every integer, to do it we use the method_missing.

def method_missing(meth, *args)
 meth.to_s =~ /_([0-9]*)!/
 return super if ! $1
 factorial($1.to_i)
end

If we use the special notation (_<digits>!) the method_missing implementation extracts the number, from the method name, and calls the factorial method to get the result. Each time and for any method the same processing happens. [3]

3. Foo_Bar

class Foz 
 def bar
   puts "Foz-bar"
 end
end
class NoBar
  def method_missing(methodname, *args)
     puts "NoBar" if "bar" == methodname.to_s
  end
end
class MakeBar
  define_method(:bar) {puts "madebar"}
end
bu= Baruser.new
bu.baruse(Foz.new) # another type altogether
bu.baruse(NoBar.new) # a class that doesn't have bar method
bu.baruse(MakeBar.new) # a class where the bar method is created programatically 

We can see from the examples that what ruby does is searching for a handler for the bar message. The handler can be a method (symbol) called bar or a generic handle like Missing_Method -- Ruby doesn't care as long as the message get handled. [4]

Advantages

  1. Allow you to catch problem at runtime.
  2. Allow you define a generic method_missing and handle any undefined method. This is a big advantage over Java. In Java, when you call method is not define, the program will not compile.
  3. The use of method_missing falls under the general technique of metaprogramming. You can employ metaprogramming in missing_function to write a another function to handle the call.

References

  1. 10 things you should know about method_missing.[5]

Further reading

  1. Evaluation Options in Ruby. [6]
  2. IF YOU BUILD IT .. will they come [7]

External links