Ruby Meta-Programming(Ruby元编程,SUN官方文档)

Ruby Meta-Programming
Topics
• What is and Why Meta-programming?
• Ruby language characteristics (that make it a great meta-programming language)
• Introspection
• Object#send
• Dynamic typing (Duck typing)
• missing_method
• define_method


What is Meta-Programming?
什么是Meta-Programming
• Metaprogramming is the writing of computer programs that write or manipulate other programs (or themselves) as their data
Metaprogramming是一种电脑程序编写方式,把编写或操作程序作为数据
Why Meta-Programming?
• Provides higher-level abstraction of logic
可以有更高层次的逻辑抽象
> Easier to write code
更简单的写代码
> Easier to read code
更容易阅读代码
• Metaprogramming feature of Ruby language is what makes Rails a killer application.
Ruby的Metaprogramming特性使Rails更加优秀。
> For example, the Rails declarations such as "find_by_name","belongs_to" are possible because of the Meta-programming feature of Ruby language.
例如,由于Ruby的Meta-programming特性可以使Rails如此声明,"find_by_name","belongs_to".


Ruby Language Characteristics that Make It a Great Meta-Programming Language
Ruby Language Characteristics
Ruby语言特性
• Classes are open
类是开放的
• Class definitions are executable code
类可扩展
• Every method call has a receiver
每一个方法调用都有接收者
• Classes are objects
类是对象化的

Classes Are Open
• Unlike, Java and C++, methods and instance variables can be added to a class (including core classes provided by Ruby such as String and Fixnum) during runtime.
不同与java和C++,在Ruby里,方法,实例变量能在运行时添加到一个类里(包括Ruby的核心类,例如String和Fixnum)
• Example: Define a new method for String class
例:给String类定义一个新方法
  1. class String
  2.   def encrypt
  3.     tr "a-z","b-za"
  4.   end
  5. end

  6. puts "cat"
  7. puts "cat".encrypt
• Benefits
好处
> Applications can be written in higher level abstraction
程序可以更加抽象的编写
> More readable code
代码更加可读
> Less coding
编写量减少
• How it is used in Rails
怎么应用在Rails里
> One can open up Rails classes and add new features to them.
可以打开一个Rails类,并添加新特性
> Rails integration testing
Rails集成测试

Class Definitions are Executable Code
类是可扩展的
• The log(msg) method is defined differently during runtime
log方法可以在运行时改变定义
  1. class Logger
  2.   if ENV['DEBUG']
  3.     def log(msg)
  4.       STDERR.puts "LOG:" +msg
  5.     end
  6.   else
  7.     def log(msg)
  8.     end
  9.   end
  10. end
Classes Are Objects
类是对象化的
• String class is an instance of Class class in the same way Fixnum class (or whatever class) is an instance of Class class
String类是Class类的一个实例,同理,Fixnum类是Class类的一个实例
  1. class Person
  2.   
  3.   puts self # Person is an instance of Class
  4.   
  5.   def self.my_class_method
  6.     puts  "This is my own class method"
  7.   end
  8.   
  9. end
Every Method Call Has a Receiver
• Default receiver is self
默认的接收者就是本身


Introspection
What is Introspection?
• Being able to find information on an object during runtime
可以在运行时查找一个对象的信息
Examples
> Object#respond_to?
> Object#class
> Object#methods
> Object#class.superclass
> Object#class.ancestors
> Object#private_instance_methods()
> Object#public_instance_methods(false)
> ...

Dynamic Method Invocation through Object#send
用Object#send进行动态方法调用
• In Ruby, an object’s methods are not fixed at any compilation time but can be dynamically extended or modified at any point.
在Ruby里,对象的方法并不一定适合编译,但能够动态的扩展或修改在任何地方。
• Instead of calling a method directly by name as following
替代如下的根据名字直接进行方法调用
> an_object_instance.hello(“Good morning!”)
• It is possible instead to invoke generically any object method by using a string or symbol variable to specify the target method
可以通过字符串或符号变量定义目标方法来替代对象方法的直接di
> an_object_instance.send(”#{name_of_method}”, args)

obj.send(symbol [, args...])
• Invokes the method identified by symbol, passing it any arguments specified.
调用标识符定义的方法,传递任意指定的参数。
  1. class Klass
  2.   def hello(*args)
  3.     "Hello " + args.join(' ')
  4.   end
  5. end

  6. k = Klass.new

  7. #The following statements are equivalent
  8. puts k.hello("gentle""readers")       #=> "Hello gentle readers"
  9. puts k.hello "gentle""readers"        #=> "Hello gentle readers"
  10. puts k.send(:hello"gentle""readers")#=> "Hello gentle readers"
  11. puts k.send :hello"gentle""readers" #=> "Hello gentle readers"


Dynamic Typing(Duck Typing)
What is Dynamic Typing?
• A programming language is said to use dynamic typing when type checking is performed at run-time (also known as "late-binding") as opposed to compile-time.
使用动态类型的程序语言在运行时检查数据类型(又称“懒加载”),这与编译时相对。
> Examples of languages that use dynamic typing include PHP, Lisp, Perl, Python, Ruby, and Smalltalk.
动态语言包括PHP, Lisp, Perl, Python, Ruby, and Smalltalk.

What is Duck Typing
• Duck typing is a style of dynamic typing in which an object's current set of methods and properties determines the valid semantics, rather than its inheritance from a particular class.
Duck类型是一个对象当前的方法和属性决定于正确的语义,而不是决定于继承一个类。
> The name of the concept refers to the duck test, attributed to James Whitcomb Riley, which may be phrased as “If it walks like a duck and quacks like a duck, I would call it a duck”.
这个名字的含义涉及到鸭子,由James Whitcomb Riley提出,可以理解为“如果一个东西走路像鸭子,叫声像鸭子,那就叫它鸭子吧
”。
Duck Typing Example (page 1)
  1. # The Duck class
  2. class Duck
  3.   def quack
  4.     puts "Duck is quacking!"
  5.   end
  6. end

  7. #The Mallard class
  8. class Mallard
  9.   def quack
  10.     puts "Mallard is quacking!"
  11.   end
  12. end

  13. #If it quacks like a duck, it must be duck
  14. def quack_em(ducks)
  15.   ducks.each do |duck|
  16.     if duck.respond_to? :quack
  17.       duck.quack
  18.     end
  19.   end
  20. end

  21. birds = [Duck.new, Mallard.newObject.new]

  22. puts "----Call quack method for each item of the birds array.Only Duck and Mallard should be quacking."
  23. quack_em(birds)


missing_method
NoMethodError Exception
• If a method that is not existent is in a class is invoked,NoMethodError exception will be generated
如果一个方法在调用的函数里不存在,将会抛出NoMethodError异常
  1. class Dummy
  2. end
  3. puts "----Call a method that does not exist in the Dummy class
  4. and expect NoMethodError exception."
  5. dummy = Dummy.new
  6. dummy.call_a_method_that_does_not_exist
method_missing Method
• If method_missing(m, *args) method is defined in a class, it will be called (instead of NoMethodError exception being generated) when a method that does not exist is invoked
如果method_missing(m, *args)方法被定义在一个类里,当一个不存在方法被调用时,这个方法将被调用(替代抛出NoMethodError)
  1. class Dummy
  2.   def method_missing(m, *args)
  3.     puts "There's no method called #{m} here -- so method_missing method is called."
  4.     puts " with arguments #{args}"
  5.   end
  6. end
  7. dummy = Dummy.new
  8. dummy.a_method_that_does_not_exist

How method_missing Method is used in Rails
method_missing方法如何在Rails里应用
• Rails' find_by_xxxx() finder method is implemented through method_missing.
Rails的find_by_xxxx()方法就由method_missing实现
  1. class Finder
  2.   def find(name)
  3.     puts "find(#{name}) is called"
  4.   end
  5.   
  6.   def method_missing(name, *args)
  7.     if /^find_(.*)/ =~ name.to_s
  8.       return find($1)
  9.     end
  10.     super
  11.   end
  12. end

  13. f = Finder.new
  14. f.find("Something")
  15. f.find_by_last_name("Shin")
  16. f.find_by_title("Technology Architect")

define_method
• The define_method defines an instance method in the receiver.
define_method 定义一个实例方法在接收者。
  1. define_method(symbol, method) => new_method
  2. define_method(symbol) { block } => proc
• The method parameter can be a Proc or Method object.If a block is specified, it is used as the method body.
方法参数可以是一个Proc或Method对象。如果block被指定,将被作为方法体。
• An example of
> define_method(symbol) { block } => proc
  1. class Love
  2.   define_method(:my_hellodo |arg1, arg2|
  3.     puts "#{arg1} loves #{arg2}"
  4.   end
  5. end

  6. love = Love.new
  7. love.my_hello("Sang Shin""Young Shin")


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值