include, extend, class_eval 用法

来源:互联网 发布:虚拟淘宝店怎么开 编辑:程序博客网 时间:2024/05/17 14:17

引用 :http://www.neeraj.name/blog/articles/503

 

 

Ruby is fun. However it took me a while to understand various semantics like include, extend, module_eval, class_eval. It all gets confusing in the beginning. Here are series of cases illustrating the simple concept of having a person with an instance method name and and a class method count.

# Case 1# Simple case of a class having an instance method and a class methodclass Person  def self.count    21  end  def name    "Neeraj"  endendputs Person.countputs Person.new.name
# Case 2# A class includes a module to have an instance methodmodule PersonName  def name    "Neeraj"  endendclass Person  def self.count    21  end  include PersonNameendputs Person.countputs Person.new.name
# Case 3# A module with self.method doesn't become a class method as # it might seem on the surfacemodule PersonModule  def name    "Neeraj"  end  def self.count    21  endendclass Person  include PersonModuleendputs Person.new.name# Following operation does not work. Exception message is undefined # method `count' for Person:Class (NoMethodError)puts Person.count 
# Case 4# Including a module and thus creating a class method is a bit tricky. # Simpler solutions are  presented in next versions.module PersonModule  def self.included(base_class)    base_class.extend(ClassMethods)  end  def name      "Neeraj"  end   module ClassMethods    def count      21    end  endendclass Person  include PersonModuleendputs Person.new.nameputs Person.count 
# Case 5# Extending a module creats the class method. # Contrast it with the include module_name (presented later)module PersonModule  def count    21  endendclass Person  extend PersonModule    def name      "Neeraj"  endendputs Person.new.nameputs Person.count 
# Case 6# Mix and match. Use both include and extend to get instance and class methods.module PersonModuleCount  def count    21  endendmodule PersonModuleName  def name    "Neeraj"  endendclass Person    extend PersonModuleCount  include PersonModuleNameendputs Person.new.nameputs Person.count 
# Case 7# Accessing the anonymous class to create a class methodmodule PersonModuleCount  def count    21  endendmodule PersonModuleName  def name    "Neeraj"  endendclass Person    class << self    include PersonModuleCount  end  include PersonModuleNameendputs Person.new.nameputs Person.count 
# Case 8# Another way of creating a class method class << personmodule PersonModuleCount  def count    21  endendmodule PersonModuleName  def name    "Neeraj"  endendclass Person    include PersonModuleNameendclass << Person      include PersonModuleCountendputs Person.new.nameputs Person.count 
# Case 9# Usage of class_evalclass PersonendPerson.class_eval do   def name    "Neeraj"  end  def self.count    21  end  endputs Person.new.nameputs Person.count 
# Case 10# Usage of class_eval in different flavor.class PersonendPerson.class_eval <<-EOF  def name    "Neeraj"  end  def self.count    21  end  EOFputs Person.new.nameputs Person.count 
# Case 11# Metaprogramming. Creating methods by defining them on run time.class_name = "Person"klass = Object.const_set(class_name,Class.new)klass.class_eval do  class << self    define_method(:count) do       21    end  end  define_method(:name) do     "Neeraj"      endendputs Person.new.nameputs Person.count 
# Case 12# Usage of send to include modules. Plugins use this pattern often.module PersonModuleCount  def count    21  endendmodule PersonModuleName  def name    "Neeraj"  endendclass Person    class << self    include PersonModuleCount      end  send(:include, include PersonModuleName)endputs Person.new.nameputs Person.count 
# Case 13# Imagine this case. A class includes a module. An instance of this class iscreated.# Then a new method is added to the module. Will the object instance willl have# this method  which was added to the module after the object was created.module PersonName  def name    "Neeraj"  endendclass Person  def self.count    21  end  include PersonNameendperson = Person.newmodule PersonName  def name2    "Neeraj"  endendputs person.name2# it works. It works because when the metho name2 is executed and this method isnot# found in the class then control looks for the included module. It means the# methods inside module are not embedded in the object when it was created.Rather# it was just a soft reference.# Let's take this case to next level. Let's add a new include to the class afterthe# object is created. This will tell us if all the list of includes are scannedduring# run time or the list of includes are embedded inside the object when it was# createdmodule PersonLate  def late_name    "I was added later"  endendclass Person  include PersonLateendputs person.late_name# it works. It menas ruby actually scans for the includes during the run timeand# creating an object is well, put it simply, just an object.# include is a method.