在任何时候,对象接收到它不能响应消息的时候,说明 这个消息不能在对象的查找路径中匹配任何方法,这个方法就被执行。
class Teacher
PEOPLE=[]
attr_reader :name, :hobbyies
def initialize(name)
@name=name
@hobbies=[]
PEOPLE<<self
end
def has_hobby(hobby)
@hobbies<<hobby
end
end
z= Teacher.new(“张三”)
w=Teacher.new(“王二”)
g=Teacher.new(“高一”)
z…has_hobby(“唱歌”)
Teacher.all_with_hobbies(“唱歌”).each do |teacher|
puts "#{teacher.name } 的爱好是 唱歌 "
end
输出结果 张三的爱好是唱歌
总体思路:根据爱好来查找老师,这个查找是根据 all_with_hobbies 这个类方法实现的。
下面我们用 method_missing 方法,判定Teacher类是否定义 hobby方法。
因为 method_missing是类方法,所以需要在Teacher类定义
def self.method_missing(m,*args)
method=m.to_s
if method.start_with?("all_with_")
# here code
else
super
end
end
首先我们调用 to_s方法将方法名称从符号格式转化method_missing 方法中可用的字符串,如果字符串中包含all_with_j继续执行代码,放到super当中,也就是往上一级继续寻找。
if method_start_with?("all_with_")
attr=method[9..-1]
if self.public_method_defined?(attr)
PEOPLE.find_all do |teacher|
person.send(attr).include?(args[0])
else
"方法名称错误 #{attr}",
end
end
通过内置查询方法,public _menthod_defined?,从而person 是否有一个与all_with_字符串的尾部名称相同的方法。
*args 参数接收了第一个元素的数组元素,这个参数为爱好值在args[0] 中