面试中碰到一些面试官提到的关于ruby元编程的问题的总结
- class和module的区别
- 官方说明
-
class doc 类是第一类型(
first-class
)的对象,每一个类都是Class
类的对象。 -
module doc 模块(
Module
)是方法和常量的集合。方法可以是实例方法也可以是模块方法,当一个模块被include
到一个类中时,实例方法会出现在该类中,而模块方法是不会出现的。
-
class doc 类是第一类型(
module Mod
def one
"This is one"
end
module_function :one
end
class Cls
include Mod
def call_one
one
end
end
Mod.one #=> "This is one"
c = Cls.new
c.call_one #=> "This is one"
module Mod
def one
"This is the new one"
end
end
Mod.one #=> "This is one"
c.call_one #=> "This is the new one"
- extend & include & prepend
module A
def t
puts "t method in A"
end
end
class B
include A
end
class C
extend A
end
B将新增一个实例方法t
,C将新增一个类方法t
,同时,B的祖先链ancestors
中将增加A,而C的祖先链中没有A。
module A
def t
puts "in A"
end
end
class B
include A
def t
puts "in B"
end
end
class C
prepend A
def t
puts "in C"
end
end
B.new.t #输出 ‘in B’
C.new.t #输出 ‘in A’
puts B.ancestors
puts C.ancestors
输出如下图所示:
prepend
与include
类似,首先都是添加实例方法的,不同的是扩展module
在祖先链上的放置位置不同。
- ruby类的继承关系
所有类的基类
类的类与超类
- 方法如何调用
- 实例方法,首先在实例中找,然后在实例对象的单件类中找,之后沿祖先链依次向上找
- 类方法,首先在类的单件类中找,然后沿着类的单件类的祖先链依次向上找(类的单件类的祖先链 = 类的祖先链的各个节点的单件类组成的链)
- instance_eval & class_eval
class A
def t1
p "t1"
end
end
obj1 = A.new
def obj1.t0
p "t0"
end
class << obj1
def t2
p "t2"
end
end
class << A
def t3
p "t3"
end
end
obj1.instance_eval %{
def t4
p "t4"
end
def self.t5
p "t5"
end
}
A.instance_eval %{
def t6
p "t6"
end
}
A.class_eval %{
def t7
p "t7"
end
}
obj1.singleton_class.send(:define_method, :t8){p 't8'}
obj1.class.send(:define_method, :t9){p 't9'}
A.singleton_class.send(:define_method, :t10){p '10'}
各自拥有的方法如下图所示: