ruby的动态性

#由于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  #报错  因为父类的方法也被删除了

 

posted @ 2013-07-10 13:12  LaoQuans  阅读(435)  评论(0编辑  收藏  举报