今天稍微搜了一下很少有讲define_method跟def的中文文章,英文的也没有讲得很明白的,今天就斗胆把我的理解跟大家分享一下。
入门级别:
class Foo
def initialize x
@x = x
end
end
class Bar
define_method :initialize do |x|
@x = x
end
end
这两段代码的功能是完全一样的,但是用benchmark比较一下,明显是def要快。
require 'benchmark'
Foo = Class.new
Bar = Class.new
t = 100000
Benchmark.bm do |x|
x.report('def') {t.times {Foo.class_eval {def a;end}}}
x.report('define_method') {t.times {Bar.class_eval {define_method(:a){}}}}
end
所以第一个结论就是,def, define_method都可以的时候,用def最好了。
现在我们从语法上来分析第一段代码:def是ruby为数不多的关键字之一(连 + = * / new都不是ruby的关键字,你敢信?),def就是用来定义方法的,没什么能展开讲的了。但是define_method不一样,define_method是一个方法,这个方法的作用是产生一个新方法(方法如其名)。
define_method是一个方法,方法就有参数,define_method的参数就是要生成的方法名,所以define_method比def聪明的地方就是他可以根据参数动态的生成很方法!
入第二个门级别:
method_name = ''
puts 'Type "exit" to exit...'
class SmartClass
def self.method_added method_name
puts "New Method: #{method_name.chomp} has been created."
end
end
while method_name.chomp != 'exit'
method_name = gets
SmartClass.class_eval do
define_method(method_name) {}
end
end
这段代码中method_added是一个钩子方法(Hook),方法如其名(方法不如其名的话名字起得是要多滥),每当有新方法添加到SmartClass的时候他都会大叫一声。
运行一下,果真我们的SmartClass能根据我们的输入动态的创建方法了!
当然这不是最重要的区别。最重要的区别是:define_method能共享上下文的作用域!
class ShabbyClass
my_name = 'piecehealth'
def say_my_name
puts my_name
end
end
class SmartClass
my_name = 'piecehealth'
define_method :say_my_name do
puts my_name
end
end
SmartClass.new.say_my_name # piecehealth
ShabbyClass.new.say_my_name # NameError
def中的代码是跟上下文完全隔离的(只认识带@跟美刀的变量),my_name这个变量是读不到。而define_method就显得更加open一点,乐意结识不带任何修饰的小伙伴(变量my_name),而这个特点,将会在动态生成一些方法是变得非常常见。
class Company
attr_accessor :service_tel
def initialize name, service_tel
@name = name
@service_tel = service_tel
end
def release_new_product product_name
product = Object.const_set(product_name.capitalize, Class.new)
company = self
product.class_eval do
define_method :initialize do
@name = product_name
@company = company
end
attr_reader :company
end
end
end
apple = Company.new('Apple', '123-1234567')
apple.release_new_product('iPhone32z')
ip32z = Iphone32z.new
p ip32z # #<Iphone32z:0x25d2d70 @name="iPhone32z", @company=#<Company:0x25d3028 @name="Apple", @service_tel="123-1234567">>
p ip32z.company.service_tel # "123-1234567"
apple.service_tel = '321-7654321'
p ip32z.company.service_tel # "321-7654321"
最后一段代码:一个公司的类Company,每当某个公司发布一个新产品,将自动建立一个新的关于该产品类,并且产品的生产厂商将自动设成它的出场公司,不用加任何多余参数。代码16行的成功读到这个类外面(12行)定义的company信息,使这个过程变得轻松愉快易维护。
分享到:
相关推荐
用于fluent中模拟物面变形运动的udf,用到Define_Grid_Motion
DEFINE_DPM_EROSION用于fluent UDF磨损
动网格,DEFINE_CG_MOTION,DEFINE_GRID_MOTION,很好的模板
需要安装rBench进行测试 gem install rbench 博文链接:https://yapex.iteye.com/blog/220596
fluent DEFINE_CG_MOTION实现动网格计算
动网格,DEFINE_CG_MOTION,DEFINE_GRID_MOTION,很好的模板(dynamic mesh good template)
使用send , define_method和method_missing遍历不同的元编程技术 将您的思维扩展到元编程,并让您考虑可以在自己的代码中利用它的地方 设置 要求 该讲习班是使用Ruby 1.9.3创建的,但是在2.1.2版本中有效。 假设您...
/* define compiler specific symbols */ #if defined ( __CC_ARM ) #define __ASM __asm /*!*/ #define __INLINE __inline /*!*/ #elif defined ( __ICCARM__ ) #define __ASM __asm /*!*/
主要介绍了C++ 中pragma once 与 #ifndef _XXX_H_ #define _XXX_H_的区别的相关资料,需要的朋友可以参考下
define _CRT_SEC.docx
代码片段: 使用define_method attr_accessor方法 def self . attr_accessor? ( attr ) read_method = " #{ attr } ?" write_method = " #{ attr } =" self . send ( :define_method , read_method ) { instance_...
Used in Fluent
AIX define_host.and so on
fluent软件中采用DEFINE_CG_MOTION动网格的udf程序
define_能量源项_动量udf_udf_激光焊接Fluent_激光焊接.zip
介绍VC编程中_T()的作用,_T可以保证从ascii编码类型转换到unicode编码类型的时候,程序不需要修改。
define_能量源项_动量udf_udf_激光焊接Fluent_激光焊接_源码.zip
利用ENVI进行图层重采样程序,c#中可以正常调用