RoR - MetaProgramming
Posted vixennn
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了RoR - MetaProgramming相关的知识,希望对你有一定的参考价值。
ruby是动态语言,它有动态语言的优势与劣势
动态语言,像python与ruby 你不用提前去定义method - they need to only be "found" when invoked
calling method dynamically:
class Dog def bark puts "Woof, woof!‘ end def greet(greeting) puts greeting end end dog = Dog.new dog.bark # => Woof, woof! dog.send("bark") # => Woof, woof! dog.send(:bark) # => Woof, woof! method_name = :bark dog.send method_name # => Woof, woof! dog.send(:greet, "hello") # => hello
Dynamic Dispatch:
不需要call method 用 xxx.xxx
能用string和symbol call methods dynamically
优点:*can decide at runtime which methods to call
*The code doesn‘t have to find out until runtime which method it needs to call
Dynamic method:
class Whatever define_method :make_it_up do puts "Whatever..." end end whatever = Whatever.new whatever.make_it_up # => Whatever...
写动态方法能有效降低code量
require_relative ‘store‘ class ReportingSystem def initialize @store = Store.new @store.methods.grep(/^get_(.*)_desc/) { ReportingSystem.define_report_method_for $1 ) end def self.define_repot_methods_for (item) define_method ("get_#{item}_desc") {@store.send("get_#{item}_desc) } define_method ("get_#{item}_price") {@store.send("get_#{item}_desc) } end end r3 = ReportingSystem.new puts "#{rs.get_piano_desc} costs #{rs.get_piano_price.to_s.ljust(6.‘0‘)}" # => Excellent piano costs 120.00
Ghost method:
如果我们使用了不存在的method,会自动跳转到method_missing method,不过method_missing 可以被复写:
class Mystery #no_methods defined def method_missing (method, *args) puts "Looking for..." puts ""#{method}" with params {#{args.join(‘,‘)}} ?" puts "Sorry... He is on vacation... " yield "Ended up in method_missing" if block_given? end end m = Mystery.new m.solve_mystery("abc", 123123) do |answer| puts "And the answer is: #{answer}" end # => Looking for... # => "solve_mystery" with params (abc,123123) ? # => Sorry... He is on vacation... # => And the answer is: Ended up in method_missing
* method_missing gives you the power to "fake" the methods
* 这被叫做ghost methods 是因为 它并不真正意义上的存在
*ruby built-in classes use method_missing and dynamic methods all over the place...
Struct and OpenStruct:
Struct: 特定类的生成器,每个类都被定义为保存一组变量及其访问器(动态
方法)
OpenStruct: 对象(类似于Struct),其属性在第一次分配时动态创建(“Ghost方法”)。
Customer = Struct.new(:name, :address) do #block is optional def to_s "#{name} lives at #{address}" end end jim = Customer.new("Jim", "-1000 wall Street") puts jim # => Jim lives at -1000 wall Street require ‘ostruct‘ # => need to require ostruct for OpenStruct some_obj = OpenStruct.new(name: "Joe", age: 15) some_obj.sure = "three" some_obj.really = "yes, it is true" some_obj.not_only_strings = 10 puts "#{some_obj.name} #{some_obj.age} #{some_obj.really}" #=> Joe 15 yes,it is true
method_missing and Performance:
因为调用是直接的,所以可能会慢一些,但大多数情况下不影响。
如果考虑响应速度的话,可以考虑hybird approach
*Define a real method from inside method missing after an attempted ‘call’
Ghost methods allow you to call methods as if they are there even though they are not
Method behavior can be defined at runtime , for example based on database columns existing or not .