Ruby元编程(一)

Ruby元编程(一)

DeathKing posted @ 2011年8月20日 20:50 in Rubywith tags ruby metaprogramming 元编程 动态 特征类 元类 匿名类 单例类 singlton class eigenclass Metaclass , 26628 阅读

1.0 Ruby元编程

 
   Ruby中的元编程,是可以在运行时动态的操作语言结构(如类、模块、实例变量等)的技术。你甚至于可以在不用重启的情况下,在运行时直接键入一段新的 Ruby代码,并执行他。
 
   Ruby的元编程,也具有“利用代码来编写代码”的作用。例如,常见的 attr_accessor等方法就是如此。
 

1.1 实例变量、方法、类

 

1.1.1 对象的实例变量及方法

 
  实例变量( Instance Variables)是当你使用它们时,才会被建立的对象。因此,即使是一个类的实例对象,也可以有不同的实例变量。
 
  从技术层面上来看,一个对象(实例)只是存储了他的实例对象,并指向本实例的类。因此,一个对象的实例变量仅存在于对象中,方法(我们称之为实例方法( Instance Methods))则存在于对象的类中。这也就是为什么同一个类的实例都共享类中的方法,却不能共享实例变量了。
 
同一个类的对象可能有不同的实例变量,但共享相同的方法。
 
(同一个类的对象可能有不同的实例变量,但共享相同的方法。 DeathKing 制)
 

1.1.2 类

  • 类也是对象。
  • 因为类也是一个对象,能应用于对象的皆可运用于类。类和任何对象一样,有它们自己的类,Class类既是Class类的实例。
  • 像别的对象一样,类也有方法。对象的方法即是其所属类的实例方法。亦即,任何一个类的方法就是Class类的实例方法。
  • 所有的类有共同的祖先Object类(都是从Object类直接或间接继承而来),而Object类又继承自BasicObject类,Ruby类的根本。
  • 类名是常量(Constant)。
  下面的代码有助于你理解这些信息:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 对象的方法即为其所属类的实例方法
1 .methods == 1 . class .instance_methods
#=> true
 
# 类的“溯源”
N = Class . new
N .ancestors
#=> [N, Object, Kernel, BasicObject]
N . class
#=> Class
N .superclass
#=> Object
N .superclass.superclass
#=> BasicObject
N .superclass.superclass.superclass
#=> nil

1.1.3 类是开放的

  在 Ruby中,类从来都是开放的。你可以重定义一个类,甚至于像 StringArray这样的标准库中的类。
 
?
1
2
3
4
5
6
7
class String
   def writesize
     self .size
   end
end
 
puts "Tell me my size!" .writesize
 
注意
 
当你打开一个类的时候,一定要万分小心!如果你随意向类中添加方法或数据,你可能会收到许多的 BUG,比如,你定义了自己的 captalize()方法并且漫不经心的覆盖了原 String类中的 capitalize()方法,你很可能会收到风险。
 

1.1.4 多层次initialize()方法

 
  下面将示范一个类的重载( Overloading)。我们编写了一个 Rectangule类,该类用于将一个矩形呈现在网格上。当你在实例化一个
 
   Rectangule对象时,你可以使用两种方法:传递矩形的左上、右下的坐标,或者左上点坐标及矩形的宽度、高度。虽然 Ruby中每个类
 
  只有一个 initialize方法,但这种做法允许你的一个 initialize就像两个 initialize一样。
 
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# The Rectangle constructor accepts arguments in either
# of the following forms:
#   Rectangle.new([x_top, y_left], length, width)
#   Rectangle.new([x_top, y_left], [x_bottom, y_right])
class Rectangle
   def initialize(*args)
     if args.size < 2  || args.size > 3
       puts 'Sorry. This method takes either 2 or 3 arguments.'
     else
       puts 'Correct number of arguments.'
     end
   end
end
Rectangle. new ([ 10 , 23 ], 4 , 10 )
Rectangle. new ([ 10 , 23 ], [ 14 , 13 ])
 
  上述程序还不足以编写一个完整的 Rectangule程序,但却足以演示方法重载是如何实现的。对 initialize方法的重载可使得其具有处理可变参数的能力。这种技巧不但适用于 initialize方法,也适用于其他方法!
 

1.1.5 匿名类

 
  一个匿名类( Anonymous Class)也被称作单例类( Singleton Class),特征类( Eigenclass),鬼魂类 订正请求Ghost Class),元类( Metaclass)或者 uniclass 译名请求
 
关于 eigenclass这个名字的由来:大多数人叫它 singlton classes,另一部分人叫它 metaclasses,意思是 the class of a class。但是这些名字都不足以描述它。 Ruby之父 Matz至今还没有给出一个官方的名字,但是他似乎喜欢叫它 eigenclasseigen这个词来自于德语,意思是 one’s own。所以, eigenclass就被翻译为 “an object’s own class”。而 eigenclass的方法名字,则取了一个比较科学严肃的名字叫 Singlton Methods
 
“特征类”是一个很好的命名。这个“特征”和线性代数中“特征值”、“特征向量”的“特征”是一个意思。“特征值”、“特征向量”的名称是由德国数学家 David Hilbert (大卫·希尔伯特)在 1904 年使用并得以流传的,德语单词“ Eigen”本意为“自己的”。 Eigenclass,也就意味着“自己的类”,用于 Ruby 的“单例类”概念之上十分贴切,因为“单例类”实际上就是一个对象独有的类。
 
——参考自 紫苏特征类一文
 
 
  Ruby中每个对象都有其自己的匿名类,一个类能拥有方法,但是只能对该对象本身其作用:当我们对一个具体的对象添加方法时, Ruby会插入一个新的匿名类于父类之间,来容纳这个新建立的方法。值得注意的是,匿名类通常是不可见( Hidden)的。他没有名字因此不能像其他类一样,通过一个常量来访问。你不能为这个匿名类实例化一个新的对象。
 
  下面展示了建立匿名类的一些方法:
 
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# 1
class Rubyist
   def self .who
     "Geek"
   end
end
 
# 2
class Rubyist
   class << self
     def who
       "Geek"
     end
   end
end
 
# 3
class Rubyist
end
def Rubyist.who
   "Geek"
end
 
#4
class Rubyist
end
Rubyist.instance_eval do
   def who
     "Geek"
   end
end
puts Rubyist.who # => Geek
 
# 5
class << Rubyist
   def who
     "Geek"
   end
end
 
  上述5段代码,分别定义了 Rubylist.who方法,该方法返回 "Geek"
 
  你可以参看 Complete Ruby Class Diagram 一文,文中展示了 Ruby 1.8.6中的用户定义类及他们的超类的关系。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值