ruby元编程 那些书里没有的知识 define_method
你有多少种方式创建一个方法?大多数人想到的可能是def 关键字
具体分析下:define_method方法
可以看到define_method是一个私有方法,那么私有方法调用是有规定的:
1.不能有显式调用,也就是不能有接受者,不能self.define_method这样调用
2.私有方法是可以被继承的
3.私有方法可以被send强制调用,如:send(:private_method)
4.只能在自身中调用私有方法(体会下这句话的意思)
上面Project类中,当前self是类Project,然后隐式调用define_method方法建立方法
define_methods动态创建方法,什么是动态创建呢,就是代码运行时就创建定义了方法,利用动态创建和动态派发可以实现ruby的代码重构,这是魔法!
例子元编程书上有,中文版 46页,英文版69页
看一个例子:
1.说明define_method定义的方法和def定义没区别,都可以被继承
2.define_method的方法是存在于类中的实例方法
修改代码:
一拍脑袋,额,忘记说了,define_method是Object Class方法,也就是只有类才可以调用,
creat_method的当前self肯定是一个对象啊,对象不是类,所以不能调用,修改代码
调用方法:
崩溃了,怎么还不行,看看提示,说这是一个私有方法,额。。。忘记了,private方法不能显式有接受者,我们想到一个办法,对,那就是send方法
修改代码:
终于成功了,这种技术叫做 动态派发技术,常用在Method_messing方法。
解法2:
解法3:
研究的不好,有错误大家交流!
- #普通方法
- def tele_you
- puts "I am Anleb"
- end
#普通方法 def tele_you puts "I am Anleb" end
- #定义单件方法
- n="Anleb"
- def n.tell_you
- puts "I am #{self}"
- end
- n.tell_you
#定义单件方法 n="Anleb" def n.tell_you puts "I am #{self}" end n.tell_you
- #define_method
- class Project
- define_method :tell_you do |name|
- puts name
- end
- end
- a=Project.new
- a.tell_you("Anleb")
#define_method class Project define_method :tell_you do |name| puts name end end a=Project.new a.tell_you("Anleb")
具体分析下:define_method方法
- Kernel.private_methods.include?("define_method") #true
Kernel.private_methods.include?("define_method") #true
可以看到define_method是一个私有方法,那么私有方法调用是有规定的:
1.不能有显式调用,也就是不能有接受者,不能self.define_method这样调用
2.私有方法是可以被继承的
3.私有方法可以被send强制调用,如:send(:private_method)
4.只能在自身中调用私有方法(体会下这句话的意思)
上面Project类中,当前self是类Project,然后隐式调用define_method方法建立方法
define_methods动态创建方法,什么是动态创建呢,就是代码运行时就创建定义了方法,利用动态创建和动态派发可以实现ruby的代码重构,这是魔法!
例子元编程书上有,中文版 46页,英文版69页
看一个例子:
- class Project1
- define_method :tell_you do |name|
- puts name
- end
- end
- class Project2 < Project1
- end
- a=Project2.new
- a.tell_you("Anleb")
- Project1.instance_methods(false) #["tell_you"]
class Project1 define_method :tell_you do |name| puts name end end class Project2 < Project1 end a=Project2.new a.tell_you("Anleb") Project1.instance_methods(false) #["tell_you"]
1.说明define_method定义的方法和def定义没区别,都可以被继承
2.define_method的方法是存在于类中的实例方法
修改代码:
- class Project1
- define_method :tell_you do |name|
- puts name
- end
- def creat_method
- define_method :new_method do
- puts "this is a new method"
- end
- end
- end
- Project1.new.creat_method
- Error:test.rb:7:in `creat_method': undefined method `define_method' for #<Project1:0x2bc7008> (NoMethodError)
class Project1 define_method :tell_you do |name| puts name end def creat_method define_method :new_method do puts "this is a new method" end end end Project1.new.creat_method Error:test.rb:7:in `creat_method': undefined method `define_method' for #<Project1:0x2bc7008> (NoMethodError)
一拍脑袋,额,忘记说了,define_method是Object Class方法,也就是只有类才可以调用,
creat_method的当前self肯定是一个对象啊,对象不是类,所以不能调用,修改代码
- def creat_method
- self.class.define_method :new_method do
- puts "this is a new method"
- end
- end
def creat_method self.class.define_method :new_method do puts "this is a new method" end end
调用方法:
- Project1.new.creat_method
- Error:test.rb:7:in `creat_method': private method `define_method' called for Project1:Class (NoMethodError)
Project1.new.creat_method Error:test.rb:7:in `creat_method': private method `define_method' called for Project1:Class (NoMethodError)
崩溃了,怎么还不行,看看提示,说这是一个私有方法,额。。。忘记了,private方法不能显式有接受者,我们想到一个办法,对,那就是send方法
修改代码:
- class Project1
- define_method :tell_you do |name|
- puts name
- end
- def creat_method
- self.class.send(:define_method,:new_method) do
- puts "this is a new method"
- end
- end
- end
- a=Project1.new
- p Project1.instance_methods(false) #["creat_method", "tell_you"]
- a.creat_method
- p Project1.instance_methods(false) #["creat_method", "tell_you"]
class Project1 define_method :tell_you do |name| puts name end def creat_method self.class.send(:define_method,:new_method) do puts "this is a new method" end end end a=Project1.new p Project1.instance_methods(false) #["creat_method", "tell_you"] a.creat_method p Project1.instance_methods(false) #["creat_method", "tell_you"]
终于成功了,这种技术叫做 动态派发技术,常用在Method_messing方法。
解法2:
- class Project1
- define_method :tell_you do |name|
- puts name
- end
- def self.creat_method
- define_method :new_method do #当前self是类,所以可以调用,并且隐式
- puts "this is a new method"
- end
- end
- creat_method
- end
- Project1.new.new_method
class Project1 define_method :tell_you do |name| puts name end def self.creat_method define_method :new_method do #当前self是类,所以可以调用,并且隐式 puts "this is a new method" end end creat_method end Project1.new.new_method
解法3:
- class Project1
- class << self
- def creat_method
- define_method :new_method do #当前self是类
- puts "this is a new method"
- end
- end
- end
- creat_method
- end
- Project1.new.new_method
class Project1 class << self def creat_method define_method :new_method do #当前self是类 puts "this is a new method" end end end creat_method end Project1.new.new_method
研究的不好,有错误大家交流!