#由于eval 方法不会检查字符串的内容,这样很不安全
#所以我们经常用 module_eval class_eval instance_eval 来动态执行字符串形式的代码
class String
def truncate(n)
self[0,n]
end
for i in [5,8,10,20]
module_eval "def truncate_#{i} #注意调用的时候不能吧参数换行,否则会报参数错误
truncate #{i}
end"
end
end
puts "abcdef".truncate(2)
puts "abcdef".truncate_5
puts "abcdef".truncate_10
#对象的send 方法,用于动态调用对象的方法,已字符串为例子:
mymethod = "upcase"
puts "abcd".send(mymethod)
mymethod = "downcase"
puts "ABCD".send(mymethod)
#动态获得方法
puts Object.methods #返回Object 对象的共有方法
puts Object.instance_methods #返回Object 对象的公开实例方法
puts String.method_defined?(:reverse) #返回String 对象是否定义了一个 reverse 的实例方法
puts "str".respond_to?(:upcase) #返回类是否能相应某实例方法的调用
#const_get 的两个用处:可以获得模块或类中的常量,也可以根据某个类名称创建某个类的实例。
#简单概括就是 可以获得 常量性质的
class_name = "Array"
array_class = Object.const_get(class_name)
puts array_class.new => []
#获取和设置实例变量
#@aa = 1
#pust self.instance_variable_get("@aa"")
#self.instance_variable_set("@aa",2)
#puts @aa =>2
#动态定义方法
class Myclass
def self.new_method(name,&block)
define_method(name,&block) #动态定义方法
end
end
Myclass.new_method(:my_new_method){ puts "my_new_method"}
Myclass.new.my_new_method
#调用没定义的方法 ruby 会调用 method_missing(name,*args)
#若调用没定义的常量, 会调用 const_missing(name)
class Module
def const_missing(name)
puts "const: #{name} no define"
end
def method_missing(name,*args)
puts "method: #{name} no define"
end
end
puts String.unknown_method
puts String::Unknown_Const
#利用 const_missing 和 method_missing 可以动态实现无穷多个有规则的方法。
#利用 const_missing 自动创建所有字母的 ASCII 码
#很有用的一段代码
class Module
def const_missing(name)
match = /^ASCII_FOR_([A-Z]|[a-z])$/.match(name.to_s)
if match
return match[1][0] #返回 ASCII 码
else
return NoMethodError #报错
end
end
end
puts ASCII_FOR_A
puts ASCII_FOR_z
#method_missing 查找学生,很有用的感觉
class Student
attr_accessor :name, :sex, :age, :grade
def initialize(_name,_sex,_age,_grade)
self.name = _name
self.sex = _sex
self.age = _age
self.grade = _grade
end
def to_s #覆盖自身的 to_s方法
self.name
end
end
class School < Array
def find_student(by,value) #查找学生
puts by
self.find_all{|s| s.send(by)==value}
end
def add_student(student)
self<<student
end
def method_missing(name,argument)
match = /^find_student_by_([a-z]+)$/.match(name.to_s)
if match
find_student match[1],argument
else
raise NoMethodError
end
end
end
school = School.new
school.add_student(Student.new("zhangsan","male",16,"3"))
school.add_student(Student.new("lisi","male",13,"1"))
school.add_student(Student.new("liyuan","female",16,"3"))
school.add_student(Student.new("wangqiang","male",16,"2"))
puts school.find_student_by_name("zhangsan")
puts "=========="
puts school.find_student_by_sex("male")
puts "=========="
puts school.find_student_by_age(13)
puts "=========="
puts school.find_student_by_grade("3")
#动态删除定义
#undef 取消定义的方法
#Module类还提供了下面方法来删除定义
#remove_method 删除方法 删除当前的方法定义
#undef_method 删除方法 连父类的方法也删除
#remove_const 删除常量
#eg:
def test_function
puts "test_function"
end
undef test_function
# test_function 报错,被 undef 了
class Myclass
def method1
puts "method1"
end
def method2
puts "method2"
end
end
class MySubclass < Myclass
def method1
puts "method1"
end
def method2
puts "method2"
end
remove_method :method1
undef_method :method2
end
sub_class = MySubclass.new
sub_class.method1 #输出 method1
# sub_class.method2 #报错 因为父类的方法也被删除了