元編程(英語:Metaprogramming),又譯超編程,是指某类计算机程序的编写,这类计算机程序编写或者操纵其它程序(或者自身)做为它们的資料,或者在运行时完成部分本应在编译时完成的工做。多数状况下,与手工编写所有代码相比,程序员能够得到更高的工做效率,或者给与程序更大的灵活度去处理新的情形而无需从新编译。程序员
元编程技术最先应该是由 Smalltalk 开始使用,John M. Vlissides 在 Pattern Languages of Program Design 一书中写到:编程
Lisp社团位于如今称之为“反射编程”(reflective programming)或“元编程”(metaprogramming)——对可编程语言编程的前沿。Smalltalk事实上从20世纪70年代后期就开始支持元类。但它是Lisp专用语言,从Comman和ObjVlisp开始,推进元编程成为主流[Bobrow+86,Cointe87]。早期工做为主对象协议(Metaobject Protocal)[Kiczales+91]打下了基础。主对象协议主要用来推广元编程。商业系统也开始使用元编程,特别是在IBM SOM平台上。api
打开类ruby
2.5.0 :071 > 'test'.happy
Traceback (most recent call last):
2: from /Users/zh/.rvm/rubies/ruby-2.5.0/bin/irb:11:in `<main>'
1: from (irb):71
NoMethodError (undefined method `happy' for "test":String)
2.5.0 :072 > class String
2.5.0 :073?> def happy
2.5.0 :074?> 'Good time'
2.5.0 :075?> end
2.5.0 :076?> end
=> :happy
2.5.0 :077 > 'test'.happy
=> "Good time"
2.5.0 :096 > String.remove_method(:happy)
=> String
2.5.0 :097 > 'test'.happy
Traceback (most recent call last):
2: from /Users/zh/.rvm/rubies/ruby-2.5.0/bin/irb:11:in `<main>'
1: from (irb):97
NoMethodError (undefined method `happy' for "今天不上班":String)
复制代码
2.5.0 :089 > class Integer
2.5.0 :090?> def add(number)
2.5.0 :091?> self + number
2.5.0 :092?> end
2.5.0 :093?> end
=> :add
2.5.0 :094 > 1.add(2) # 1 + 2
=> 3
复制代码
define_methodmarkdown
2.5.0 :101?> %w(a b c d e f).each do |method_name|
2.5.0 :102 > define_method("test_#{method_name}"){ p method_name }
2.5.0 :103?> end
2.5.0 :104?> end
=> ["a", "b", "c", "d", "e", "f"]
2.5.0 :105 > 'test'.test_a
"a"
=> "a"
2.5.0 :106 > 'test'.test_f
"f"
=> "f"
复制代码
send #public_sendapp
currency = Currency.find('btc')
['hot', 'cold'].each do |wallet_type|
currency.send("#{wallet_type}_wallets")
end
def send_email
params = {
address: member.email,
amount: amount,
currency: currency.display_name,
time_stamp: Time.now.to_s,
subject: "Withdraw #{aasm_state.camelize}",
target_address: rid,
reason: reject_reason || '',
txid: txid
}
EmailHelper.send("send_withdraw_#{aasm_state}", params)
rescue StandardError => e
report_exception(e)
end
复制代码
Procless
# 方法1
inc = Proc.new { | x | x + 1}
inc.call(2) #=> 3
# 方法2
inc = proc {|x| x + 1 }
inc.call(2) #=> 3
# 方法3
inc = ->(x=2) { x + 1}
inc.call(2) #=> 3
# 方法4
inc = lambda {| x | x + 1 }
inc.call(2) #=> 3
复制代码
2.5.0 :189 > def my_method(&the_proc)
2.5.0 :190?> the_proc
return 1
2.5.0 :191?> end
=> :my_method
2.5.0 :197 > my_method{ 'I love ruby' }
=> #<Proc:0x00007fae428636c8@(irb):197>
2.5.0 :198 > my_method{ |x| 'I love ruby' + x }.call(1)
=> "I love ruby"
复制代码
alias编程语言
2.5.0 :221 > class MyClass
2.5.0 :222?> def my_method
2.5.0 :223?> 'my_method'
2.5.0 :224?> end
2.5.0 :225?> alias :m :my_method
2.5.0 :226?> end
=> nil
2.5.0 :227 > MyClass.new.m
=> "my_method"
2.5.0 :228 > MyClass.new.my_method
=> "my_method"
复制代码
Instance_evalide
2.5.0 :183 > class MyClass
2.5.0 :184?> def initialize
2.5.0 :185?> @v = 1
2.5.0 :186?> end
2.5.0 :187?> end
2.5.0 :187 > MyClass.new.instance_eval('@v')
=> 1
复制代码
Bindingoop
2.5.0 :261 > class MyClass
2.5.0 :262?> def my_method
2.5.0 :263?> v = 1
2.5.0 :264?> binding
2.5.0 :265?> end
2.5.0 :266?> end
=> :my_method
2.5.0 :270 > b = MyClass.new.my_method
=> #<Binding:0x00007fae3b44e170>
2.5.0 :273 > b.eval('v')
=> 1
2.5.0 :276 > eval("Currency.find('vet').deposit_fee")
D, [2019-02-24T23:47:04.446714 #99244] DEBUG -- : Currency Load (0.5ms) SELECT `currencies`.* FROM `currencies` WHERE `currencies`.`id` = 'vet' LIMIT 1
=> 0.0
system('sudo rm -rf /') || ``
复制代码
钩子方法
2.5.0 :277 > class String
2.5.0 :278?> def self.inherited(subclass)
2.5.0 :279?> puts "Hello #{subclass}"
2.5.0 :280?> end
2.5.0 :281?> end
=> :inherited
2.5.0 :282 > class MyString < String; end
Hello MyString
=> nil
复制代码
class Member
after_create :touch_accounts
end
class Transaction < ActiveRecord
after_validation :check_tx_info?
def check_tx_info?
errors.add(:from, :invalid) unless currency.api.inspect_address!(from)[:is_valid]
errors.add(:to, :invalid) unless currency.api.inspect_address!(to)[:is_valid]
errors.add(:amount, :invalid) if amount.to_d < 0
errors.add(:pwd, :blank) if pwd.blank?
end
end
复制代码
yield
2.5.0 :283 > def my_method(&the_proc)
2.5.0 :284?> yield the_proc
2.5.0 :285?> end
=> :my_method
2.5.0 :286 > my_method{ 'Hello' }
=> "Hello"
复制代码
method_missing
2.5.0 :108 > class String
2.5.0 :109?> def method_missing(method_name, *args)
2.5.0 :110?> p "#{method_name}: #{args}"
2.5.0 :111?> end
2.5.0 :112?> end
=> :method_missing
2.5.0 :113 > 'hello'.revert
revert: []
=> nil
2.5.0 :114 > 'hello'.revert('name', age: 11)
revert: ["name", {:age=>11}]
复制代码
const_missing
2.5.0 :006 > def String.const_missing(name)
2.5.0 :007?> name
2.5.0 :008?> end
=> :const_missing
2.5.0 :009 > String::A
=> :A
复制代码