Ruby元编程

11 分钟阅读

eval函数

该函数将字符串解析成代码,如下示例

  • 传入变量字符串,解析成变量
    test = "abc"
    puts eval("test")
    #打印abc
    puts eval("0x12")
    #打印18
    
  • 传入函数字符串,解析调用后的结果
    def func(a)
    return a*a
    end
    puts eval("func(10)")
    #打印100
    

class方法(类/对象)

该方法可以得到变量的类,如下示例

"abc".class #String 类
"abc".class.name #"String" 类名
"abc".class.new("ef") #用"abc"的类创建一个新类,内容是"ef"
"abc".class.methods #得到String类的所有方法,等同于String.methods
"abc".class.methods.class #Array

不仅仅实例有自己的类,类本身也有自己的类

String.class #Class
Classs.class #Class

superclass方法(类)

该方法可以得类的父类(超类),如下示例

Integer.superclass #Numeric
Numeric.superclass #Object
Object.superclass  #BasicObject
BasicObject.superclass #nil

ancestors方法(类)

该方法可以得类的祖先链

Integer.ancestors
# [Integer, Numeric, Comparable, Object, Kernel, BasicObject]

methods方法(类/对象)

该方法可以得到实例或类的所有方法,数组形式

123.methods
# 这是实例的所有方法
# [:%, :&, :*, :+, :-, :/, :<, :>, :^, :|, :~, :-@, :**, :<=>, :<<, :>>, :<=, :>=, :==, :===, :[], :inspect, :size, :succ, :to_int, :to_s, :to_i, :to_f, :next, :div, :upto, :chr, :ord, :coerce, :divmod, :fdiv, :modulo, :remainder, :abs, :magnitude, :integer?, :floor, :ceil, :round, :truncate, :odd?, :even?, :downto, :times, :pred, :bit_length, :digits, :to_r, :numerator, :denominator, :rationalize, :gcd, :lcm, :gcdlcm, :+@, :eql?, :singleton_method_added, :i, :real?, :zero?, :nonzero?, :finite?, :infinite?, :step, :positive?, :negative?, :quo, :arg, :rectangular, :rect, :polar, :real, :imaginary, :imag, :abs2, :angle, :phase, :conjugate, :conj, :to_c, :between?, :clamp, :instance_of?, :kind_of?, :is_a?, :tap, :public_send, :define_singleton_method, :method, :public_method, :remove_instance_variable, :instance_variable_set, :singleton_method, :extend, :to_enum, :enum_for, :=~, :!~, :respond_to?, :freeze, :object_id, :send, :display, :nil?, :hash, :class, :singleton_class, :clone, :dup, :itself, :taint, :tainted?, :untaint, :untrust, :untrusted?, :trust, :frozen?, :methods, :singleton_methods, :protected_methods, :private_methods, :public_methods, :instance_variable_get, :instance_variables, :instance_variable_defined?, :!, :!=, :__send__, :equal?, :instance_eval, :instance_exec, :__id__]
Integer.methods
# 这是类的所有方法,注意与123.methods不同
# [:allocate, :superclass, :<=>, :include, :<=, :>=, :==, :===, :included_modules, :include?, :name, :ancestors, :instance_methods, :public_instance_methods, :protected_instance_methods, :private_instance_methods, :constants, :const_get, :const_set, :const_defined?, :class_variables, :remove_class_variable, :class_variable_get, :class_variable_set, :class_variable_defined?, :public_constant, :private_constant, :deprecate_constant, :singleton_class?, :module_exec, :class_exec, :freeze, :inspect, :const_missing, :class_eval, :method_defined?, :public_method_defined?, :prepend, :<, :>, :private_method_defined?, :protected_method_defined?, :public_class_method, :module_eval, :to_s, :private_class_method, :autoload, :autoload?, :instance_method, :public_instance_method, :instance_of?, :kind_of?, :is_a?, :tap, :public_send, :define_singleton_method, :method, :public_method, :remove_instance_variable, :instance_variable_set, :singleton_method, :extend, :to_enum, :enum_for, :=~, :!~, :eql?, :respond_to?, :object_id, :send, :display, :nil?, :hash, :class, :singleton_class, :clone, :dup, :itself, :taint, :tainted?, :untaint, :untrust, :untrusted?, :trust, :frozen?, :methods, :singleton_methods, :protected_methods, :private_methods, :public_methods, :instance_variable_get, :instance_variables, :instance_variable_defined?, :!, :!=, :__send__, :equal?, :instance_eval, :instance_exec, :__id__]

instance_methods方法(类)

该方法可以得到类的实例方法,数组形式

Integer.instance_methods
# 这是实例方法,注意与123.methods相同
# [:%, :&, :*, :+, :-, :/, :<, :>, :^, :|, :~, :-@, :**, :<=>, :<<, :>>, :<=, :>=, :==, :===, :[], :inspect, :size, :succ, :to_int, :to_s, :to_i, :to_f, :next, :div, :upto, :chr, :ord, :coerce, :divmod, :fdiv, :modulo, :remainder, :abs, :magnitude, :integer?, :floor, :ceil, :round, :truncate, :odd?, :even?, :downto, :times, :pred, :bit_length, :digits, :to_r, :numerator, :denominator, :rationalize, :gcd, :lcm, :gcdlcm, :+@, :eql?, :singleton_method_added, :i, :real?, :zero?, :nonzero?, :finite?, :infinite?, :step, :positive?, :negative?, :quo, :arg, :rectangular, :rect, :polar, :real, :imaginary, :imag, :abs2, :angle, :phase, :conjugate, :conj, :to_c, :between?, :clamp, :instance_of?, :kind_of?, :is_a?, :tap, :public_send, :define_singleton_method, :method, :public_method, :remove_instance_variable, :instance_variable_set, :singleton_method, :extend, :to_enum, :enum_for, :=~, :!~, :respond_to?, :freeze, :object_id, :send, :display, :nil?, :hash, :class, :singleton_class, :clone, :dup, :itself, :taint, :tainted?, :untaint, :untrust, :untrusted?, :trust, :frozen?, :methods, :singleton_methods, :protected_methods, :private_methods, :public_methods, :instance_variable_get, :instance_variables, :instance_variable_defined?, :!, :!=, :__send__, :equal?, :instance_eval, :instance_exec, :__id__]

instance_variables方法(类)

该方法得到实例的成员变量,数组形式

class Cat
  def method
    @name = "Cat ^_^"
    @kind = "animal"
  end
end
cat = Cat.new
puts cat.instance_variables.inspect
#打印[]
cat.method
puts cat.instance_variables.inspect
#打印[:@name, :@kind]

打开类

直接打开已有的类,添加内容,如下示例

class String
  def title
    "$ " + self
  end
end

puts "abc".title
#打印$ abc

符号与字符串

x = "abc"
#字符串与符号的差别
x.class #String
:x.class #Symbol
#字符串与符号的互换
x.to_sym   #:abc
:x.to_s    #"x"

动态派发send与respond_to?方法(对象)

send用于向对象的成员发消息,respond_to用于判断对象是否存在成员符号; send对于私有成员也有效,public_send只能访问共有成员

x = "abc"
x.upcase #"ABC"
x.send(:upcase) #"ABC"
x.send("upcase") #"ABC"
x.respond_to?(:upcase) #true
x.respond_to?(:upxxxx) #false

通过动态派发,可以实现函数的动态调用

def get_Lucy_age
  18
end
def get_Lily_age
  19
end
#对以上方法重构
def age(name)
  send("get_#{name}_age")
end
age("Lucy") #18

幽灵方法method_missing与respond_to_missing?

当调用的方法不存在时,就调用methon_missing方法

class NameAge
  def get_Lucy_age
    18
  end
  def get_Lily_age
    19
  end
end
#对以上方法重构
class Age
  def initialize
    @nameAge = NameAge.new
  end
  def respond_to_missing?(name)
    @nameAge.respond_to?("get_#{name}_age")
  end
  def method_missing(name,*arg)
    super if !@nameAge.respond_to?("get_#{name}_age")
    @nameAge.send("get_#{name}_age")
  end
end
age = Age.new
puts age.Lucy  #18
puts age.Bob  #没有定义