`
piecehealth
  • 浏览: 47584 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Ruby define_method def 的区别

    博客分类:
  • Ruby
 
阅读更多
今天稍微搜了一下很少有讲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信息,使这个过程变得轻松愉快易维护。
0
0
分享到:
评论

相关推荐

    Ruby Meta Programming: define_method or class_eval

    `define_method`和`class_eval`是Ruby元编程中的两个关键方法,它们被广泛用于动态地添加方法到类或者模块中。这篇文章将深入探讨这两个方法的用法和区别。 `define_method`方法允许我们传递一个符号和一个代码块来...

    patch_def_ruby_Metaprogramming_Before_

    在Ruby中,元编程的一个常见工具是`Module#define_method`,它可以让我们在运行时动态地定义方法。然而,如果我们要实现`def_before`这样的功能,我们需要创建一个可以拦截并控制方法调用的机制。下面我们将深入探讨...

    Ruby元编程之梦中情人method_missing方法详解

    总的来说,理解何时和如何使用`method_missing`和`define_method`是掌握Ruby元编程的关键。`method_missing`提供了一种强大的灵活性,但其代价是性能和可读性,而`define_method`则在保持代码整洁的同时提供了动态...

    MetaProgramming-Play:重写 Ruby 注入方法以了解元编程

    代码片段: 使用define_method attr_accessor方法 def self . attr_accessor? ( attr ) read_method = " #{ attr } ?" write_method = " #{ attr } =" self . send ( :define_method , read_method ) { instance_...

    ruby metaprograming

    def self.method_missing(name, *args) puts "Called method: #{name}" end my_object = MyClass.new my_object.some_method # 输出: "Called method: some_method" ``` ##### 2. eval `eval`函数可以用来执行一...

    Ruby元编程基础学习笔记整理

    Ruby支持动态定义方法的能力,这可以通过`define_method`方法实现。 ##### 示例代码分析 ```ruby class MyClass define_method :my_method do |args| args * 3 end end obj = MyClass.new puts obj.my_method...

    ruby程序样例

    比如,你可以用`define_method`动态定义方法: ```ruby def add_method(name, &block) define_method(name, block) end add_method :greet do puts "你好!" end greet # 输出 "你好!" ``` Ruby还有许多其他...

    Ruby是一种强大而优雅的编程语言,以其简洁的语法、动态性、面向对象编程和丰富的类库而著称 以下是对Ruby的500字资源介绍:

    def self.define_method(name, &block) define_method(name, &block) end define_method(:greet) { "Hello!" } ``` #### 四、面向对象编程 作为一门纯粹的面向对象语言,Ruby将一切视为对象,包括基本的数据...

    Meta Programming Ruby

    - **动态方法定义**:假设有一个应用程序需要动态地根据用户的输入来定义新方法,可以使用`define_method`轻松实现这一点。 ```ruby class Calculator def self.define_operation(operation_name, &block) ...

    编程之魂:Ruby中的元编程艺术

    在 Ruby 中,可以使用 `define_method` 方法在运行时动态定义方法。这种方法使得程序可以根据运行时的数据和状态来自动生成特定的行为,从而提高代码的灵活性和可复用性。 #### 代码示例 ```ruby class Greeter ...

    Ruby语言入门教程&代码示例.zip

    define_method(:my_method) do puts "Inside my_method" end end my_object = MyClass.new my_object.my_method # 输出:Inside my_method ``` 以上就是Ruby语言的基础知识和关键特性,通过深入学习和实践,你...

    Ruby-Ruby的面向对象的枚举

    define_method(name.downcase) do value end end end puts DaysOfWeek::monday # 输出:1 ``` 以上就是Ruby面向对象的枚举的基本使用方式。这种实现方式不仅提供了类型安全,还允许我们根据需求扩展枚举的功能...

    metaprogramming_introduction:一篇以源代码形式介绍Ruby元编程基础知识的文章-Form source code

    define_method(:new_method) { puts 'New method defined!' } end MyClass.new.new_method # 输出 "New method defined!" ``` 在这两个例子中,`instance_eval`使我们能直接访问对象的实例变量,而`class_eval`则让...

    tiny_hooks:定义钩子的小宝石。 对库开发人员有用

    def my_method puts 'my method' end define_hook :before , :my_method do puts 'my before hook' end end MyClass . new . my_method # =&gt; "my before hook\nmy method\n" 当类/模块是您的库的基类/模块...

    Understanding Ruby's Object Model

    元编程能力允许我们编写代码来操纵代码本身,例如`define_method`可以动态定义方法。 9. **常量(Constants)** 常量以大写字母开头,一旦被赋值,其值在整个作用域内是不可变的。然而,常量的引用路径可能改变,...

    详解Ruby中的单件方法和单件类

    在Ruby编程语言中,单件方法(Singleton Method)和单件类(Singleton Class)是两个非常重要的概念。这些特性为Ruby提供了强大的灵活性,允许开发者针对特定的对象定义唯一的方法。下面将详细介绍这两者的工作原理...

    Ruby中文教程。。。

    1. 动态性:Ruby允许在运行时修改类和对象,如动态添加方法`define_method`,或在运行时改变对象的属性。 2. 方法_missing:此方法允许自定义处理未定义的方法调用,提供了一种强大的错误处理和扩展机制。 四、...

    ruby使用文档

    - `class_eval`、`instance_eval`、`define_method`等方法可用于动态定义或修改类和方法。 8. **块与 Proc**: - 块是Ruby中的匿名函数,使用`do..end`或花括号`{}`定义。 - `Proc`对象可以存储块,与`lambda`...

    first_ruby_poo

    例如,`method`, `send`, `define_method`等方法可以用来在运行时创建或修改方法。 压缩包中的“first_ruby_poo-main”可能是一个主文件或目录,包含项目的源代码。打开这个文件或目录,我们可以深入学习作者是如何...

    Ruby In a Nutshell

    - `send`方法可以调用对象的任何方法,`define_method`用于在运行时定义方法。 10. **Gem和Ruby生态系统** - Ruby的包管理器是`gem`,用于安装、管理和更新第三方库。 - Rails是Ruby最著名的Web开发框架,它基于...

Global site tag (gtag.js) - Google Analytics