Z
ZHANK
面向对象

元编程入门

define_method/class_eval/instance_eval、method_missing、反射

元编程入门

Ruby 在运行时可以定义方法、创建类、拦截方法调用——这就是元编程,Rails 的魔力来源。

学完本章你将: 掌握 define_method、class_eval、method_missing、反射。


define_method —— 运行时定义方法

ruby
class User
    ATTRIBUTES = [:name, :email, :age]

    ATTRIBUTES.each do |attr|
        define_method(attr) do
            instance_variable_get("@#{attr}")
        end

        define_method("#{attr}=") do |value|
            instance_variable_set("@#{attr}", value)
        end
    end
end

# 等价于手写了 6 个方法——attr_accessor 底层就是这样实现的

method_missing —— 拦截未知方法

ruby
class ConfigProxy
    def initialize
        @config = {}
    end

    def method_missing(method, *args, &block)
        if method.to_s.end_with?("=")
            @config[method.to_s.chomp("=").to_sym] = args.first
        else
            @config[method]
        end
    end

    def respond_to_missing?(method, include_private = false)
        true
    end
end

config = ConfigProxy.new
config.host = "localhost"   # 实际调用 method_missing
config.port = 8080
puts config.host            # "localhost"

反射

ruby
"hello".methods            # 所有方法
"hello".public_methods     # 公开方法
String.instance_methods    # String 的实例方法
User.private_methods       # 私有类方法

user.instance_variables    # [@name, @email]
user.instance_variable_get(:@name)