Ruby元编程(一)

来源:互联网 发布:百战天虫豪华版java 编辑:程序博客网 时间:2024/06/10 05:55

Ruby元编程(一)

DeathKing posted @ 2011年8月20日 20:50 in Rubywith tags ruby metaprogramming 元编程 动态特征类元类 匿名类 单例类 singlton classeigenclass 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
  defwritesize
    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
  definitialize(*args)
    ifargs.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
 
——参考自blackangerMetaprogramming Ruby的笔记(5)
“特征类”是一个很好的命名。这个“特征”和线性代数中“特征值”、“特征向量”的“特征”是一个意思。“特征值”、“特征向量”的名称是由德国数学家 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
  defself.who
    "Geek"
  end
end
 
# 2
class Rubyist
  class<< self
    defwho
      "Geek"
    end
  end
end
 
# 3
class Rubyist
end
def Rubyist.who
  "Geek"
end
 
#4
class Rubyist
end
Rubyist.instance_evaldo
  defwho
    "Geek"
  end
end
puts Rubyist.who# => Geek
 
# 5
class << Rubyist
  defwho
    "Geek"
  end
end
 
  上述5段代码,分别定义了Rubylist.who方法,该方法返回"Geek"
 
  你可以参看 Complete Ruby Class Diagram一文,文中展示了Ruby 1.8.6中的用户定义类及他们的超类的关系。

原创粉丝点击