`
haiyang
  • 浏览: 68956 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
社区版块
存档分类
最新评论

ruby元编程(入门收藏)

阅读更多
转帖:http://hi.baidu.com/mepm/blog/item/edb5e1500c75975c1038c2f6.html

元编程并不是一个很新的概念,通常元编程被认为是通过程序来生成程序,如果从这种意义上来考虑,那么lex和yacc以及JavaCC应该都可以算是具有 了元编程的概念,在Java中,元编程得到了广泛的应用。但在Ruby中,元编程的使用变得相当的简单和容易实现,使用Ruby语言本身来产生Ruby代 码,不需要借助外部的工具,著名的RoR框架就是建立的Ruby元编程的基础上的。可能你你对元编程还没什么概念,但是Ruby已经内建了元编程这种机 制,所以很有可能,你在不知不觉中就已经使用了Ruby元编程技术为你带来的方便之处。如下面这段代码:class Person
attr_reader :name
end
你肯定知道 :name 是和 @name 相关联的,但是你不一定清楚它到底是怎么实现的,其实attr_reader方法的实现就是采用了元编程技术,如下面的这段代码:

ruby 代码
 
  1. class Module  
  2. def attr_reader(*syms)  
  3.        syms.each do |sym|  
  4.          class_eval %{def #{sym}  
  5.                             @#{sym}  
  6.                      end  
  7.        end  
  8. end  
  9. end  


看了这段代码,你应该大概了解元编程的机制了吧,如果你现在还不了解,那么我建议你先认真的学习一下Ruby的反射机制,然后再接下去看这篇帖子,因为下面介绍的内容并不是一杯婴儿奶粉。

在Ruby On Rails中,有一个OR映射层,就是动态的从一张关系表映射到一个对象,这主要由ActiveRecord类来实现。在OR映射模型中,将关系数据库中的关系表表映射到对象模型时,将关系表的表名映射到类名,表中的每一个元组映射到对应于这个类的一个对象,元组的一个字段对应于对象的一个属性。

假如我们有一个保存职员基本信息的文件,文件的格式是这样的:第一行是文件内容的每个字段的名称,从第二行开始,则是每个职员的基本信息。现在我们有一个文件名为“employee.txt”的文件,其内容如下所示:

name,age,gender

"John", 23, "male"

"Linclon", 25, "male"

假设我们就 要从这个文本文件中读取数据,并进行一定的处理。如果是使用C++编程,你首先一定会想到应该定义一个Employee类,然后这个类中有name, age, gender这些成员变量。但是是采用这种方法的话,可以发现,如果想在职员信息中加入一个字段,比如部门(department),就不得不修改 Employee类的代码,在Employee类中增加一个“department”成员变量,所以我们的代码是高度依赖于文件的具体格式,这当然不是一 个好的现象。我们希望有一种更简单和优雅的方案,还有,Ruby动态性提高给我们一个解决方案,但是,我们应该从和下手呢,这就需要Ruby的元编程能 力。

首先,我们想应该有一个职员类,在Rails中,每个关系表的名称会成为类的名称,在这里,采用类似的方法,将文本文件的名称作为类的名称,在Ruby中,类名同时也是一个常量名,所以第一个字母必须为大写,我们使用如下的代码来生成类名。

class_name = File.basename(file_name, ".txt").capitalize
# "employee.txt" => "Employee"
klass = Object.const_set(class_name, Class.new)

Class.new生成一个新的类,这个类的名称是匿名的,所以采用const_set操作来绑定一个类名,变量klass是新类型的引用。


生成了这个类以后,需要想这个类添加姓名,年龄和性别这些属性,这些属性的名称是在文本文件的的第一行中给出的。

data = File.new(file_name)
header = data.gets.chomp

data.close

names = header.split(",")

下面的代码给出了如何生成这些属性,以及初始化这些属性值。
klass.class_eval do
attr_accessor *names

define_method(:initialize) do |*values|
names.each_with_index do |name, i|
instance_variable_set("@" + name, values)
end
end
#...
end

现在,有了一系列的访问子(可读和可写),通过instance_variable_set方法,又给每个属性做了初始化。

变量names是在块外部定义的,由于块的闭合性,所以变量names在块中也是有效的。当然,为了程序的演示,又定义的了一个to_s方法,代码如下所示:
define_method(:to_s) do
str = "<#{self.class}: "
names.each {|name| str << "#{name}=#{self.send(name)} "}
str + ">"
end
alias_method :inspect, :to_s

完成了这些以后,对于类的构造已经基本结束了,现在就需要真正的从文本文件中读取数据了。从文本文件读数据应该是一个类方法,而不是一个实例的方法,其实现代码如下:
def klass.read
array = []
data = File.new(self.to_s.downcase + ".txt")
data.gets #throw away header
data.each do |line|
line.chomp!
values = eval("[#{line}]")
array << self.new(*values)
end
data.close
return array
end

在这个方法中,使用字的类名来匹配相关的文件,比如将Employee类映射到“employee。txt”。

然后,从文件中读取职员信息,由于第一行是字段定义,所以要舍弃第一行数据。从第二行开始读取数据,每读取一行数据,则构造一个Employee实例。通过上面这个简单的例子,我们可以看出元编程的功能是相当之强大的,使用元编程技术,可以构造相当简单,优雅的解决方案。


class DataRecord
def self.make(file_name)
data = File.new(file_name)
header = data.gets.chomp
data.close

class_name = File.basename(file_name, ".txt").capitalize
# "employee.txt" => "Employee"
klass = Object.const_set(class_name, Class.new)
names = header.split(",")

klass.class_eval do
attr_accessor *names

define_method(:initialize) do |*values|
names.each_with_index do |name, i|
instance_variable_set("@" + name, values)
end
end

define_method(:to_s) do
str = "<#{self.class}: "
names.each {|name| str << "#{name}=#{self.send(name)} "}
str + ">"
end
alias_method :inspect, :to_s
end

def klass.read
array = []
data = File.new(self.to_s.downcase + ".txt")
data.gets #throw away header
data.each do |line|
line.chomp!
values = eval("[#{line}]")
array << self.new(*values)
end
data.close
return array
end

return klass
end
end

DataRecord.make("employee.txt")
list = Employee.read
puts list


<ouput></ouput>



非常受用。目前正在解决一个类似的问题。需要将一个返回的字符串解释成一个类。
分享到:
评论
2 楼 lamborghini_lp 2010-02-07  
最近在看Ruby元编程,感觉不容易啊。
1 楼 boobmoom 2009-09-21  
好东西 以后还得来看

相关推荐

    Ruby绝佳入门资料-双飞燕和元编程-英文版(要看就看英文)

    适合有点编程经验,先看ruby双飞燕,再看ruby元编程。 pdf,有目录,英文,这种资料尽量看英文的。 ruby双飞燕:The Ruby Programming Language ruby元编程:Pragmatic.Metaprogramming 助您学习又称

    Ruby编程语言中文版

    松本行弘原著,Ruby编程入门非常好的书籍。共两个文件

    Ruby从入门到精通

    《Ruby从入门到精通》是一本彻底而全面的最新指南,适合于各类Ruby读者,不管是编程初学者、Web开发人员,还是Ruby新手。《Ruby从入门到精通》从解说面向对象编程背后的原理开始,只通过几章的讲解,就构造出了真正...

    Ruby编程入门保姆级:轻松掌握20个核心概念!.zip技术关键词:Ruby编程语言、面向对象、类和对象、模块、方法、集合数据结

    内容概要:全面掌握Ruby编程语言,轻松应对各种开发挑战! 适用人群:适合对编程感兴趣的初学者,以及希望快速入门Ruby语言的开发者。 使用场景及目标:通过幽默风趣的语言和生动的比喻,帮助读者理解并掌握Ruby编程...

    Ruby 教程 从入门到精通

    Ruby语言 1 Grant Ren 1 第一部分 Ruby语言基础 8 第一章 Ruby语言概述 8 §1.1 Ruby的历史 8 §1.2 Ruby名字的由来 8 ...第二章 Ruby编程环境 9 §2.1 Ruby的安装 9 §2.1.1 在Windows 95/98/Me/XP上安装Ruby 9

    Ruby入门教程,张开川编著

    张开川编著的Ruby入门教程,共九章,从开始安装到元编程,简单易懂,详细,对Ruby学习很有帮助

    Ruby语言入门中文教程PDF+源代码.rar

    使用场景及目标:可用于自学、教学、编程入门等场景。通过阅读教程和实践源代码demo,读者可以学习Ruby语言的基础知识,掌握编程技巧,为将来的Ruby编程项目做好准备。 其他说明:建议读者在学习过程中结合实际练习...

    ruby入门简单demo,学习练习编程语言

    ruby入门简单demo,学习练习编程语言

    Ruby 编程语言的书籍

    这本书涵盖了 Ruby 的基础知识和高级特性,包括对象模型、控制流、模块和类、异常处理、元编程等方面的内容。它适合初学者入门,同时也提供了一些进阶的话题,能够帮助读者系统地学习和掌握 Ruby 编程语言。

    2024年Ruby快速入门(10分钟).zip

    本博客为初学者提供了一个关于Ruby编程的快速入门教程。从Ruby的介绍和特点开始,逐步介绍了如何安装Ruby、学习基本语法、动手实践和高级特性。博客还提供了Ruby的实际应用场景,如Web开发、数据处理和自动化测试。...

    openCV3编程入门(PDF+代码)

    PDF版本openCV3编程入门,以及配套的程序代码。OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,可以运行在Linux、Windows、Android和Mac OS操作系统上。它轻量级而且高效——由一系列 C 函数和少量 C++ ...

    Ruby菜鸟入门指南.md

    这份文档是Ruby编程入门指南,主要内容包括: 1. 字符串的几种表示方式(单引号、双引号、多行字符串)及其区别。 2. 符号(Symbol)的概念及作用,如用于Hash的键。 3. Ruby中"一切皆对象"的理念,数字、布尔值、类、nil...

    Ruby完全自学手册 下

    虽然定位为入门手册,但是依然涉及许多高级技术和应用,覆盖到的应用领域包括系统管理、网络编程、图形处理、图形界面开发以及web开发等开发热门领域。希望借助于平易的讲解,让读者在学习的过程中,理解Ruby的编程...

    Ruby语言入门教程

    我想,回报网络的最好方式就是在网络上还没有Ruby中文书籍的时候,编著一本Ruby中文入门教材。感谢编程语言发展史上的前辈们;感谢网络论坛上程序员们或是理智,或是激烈的讨论;感谢一切看到这本书的人。

    Elixir编程入门

    Elixir是一门建立在Erlang虚拟机上的函数式的系统编程语言,支持元编程。创始人José Valim是ruby界的知名人士。 私以为,可以把Elixir看作函数式的ruby语言,或者是语法类似ruby的Erlang。Elixir受瞩目的原因,是...

    Ruby语言入门教程v1

    一种用于迅速和简便的面向对象编程的解释性脚本语言,Ruby语言入门教程

Global site tag (gtag.js) - Google Analytics