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中的用户定义类及他们的超类的关系。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值