您的位置:首页 > 编程语言 > Ruby

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

2008-08-26 14:16 537 查看
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类定义一个新方法
class String
def encrypt
tr "a-z","b-za"
end
end

puts "cat"
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方法可以在运行时改变定义
class Logger
if ENV['DEBUG']
def log(msg)
STDERR.puts "LOG:" +msg
end
else
def log(msg)
end
end
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类的一个实例
class Person

puts self # Person is an instance of Class

def self.my_class_method
puts "This is my own class method"
end

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.
调用标识符定义的方法,传递任意指定的参数。
class Klass
def hello(*args)
"Hello " + args.join(' ')
end
end

k = Klass.new

#The following statements are equivalent
puts k.hello("gentle", "readers") #=> "Hello gentle readers"
puts k.hello "gentle", "readers" #=> "Hello gentle readers"
puts k.send(:hello, "gentle", "readers")#=> "Hello gentle readers"
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)
# The Duck class
class Duck
def quack
puts "Duck is quacking!"
end
end

#The Mallard class
class Mallard
def quack
puts "Mallard is quacking!"
end
end

#If it quacks like a duck, it must be duck
def quack_em(ducks)
ducks.each do |duck|
if duck.respond_to? :quack
duck.quack
end
end
end

birds = [Duck.new, Mallard.new, Object.new]

puts "----Call quack method for each item of the birds array.Only Duck and Mallard should be quacking."
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异常
class Dummy
end
puts "----Call a method that does not exist in the Dummy class
and expect NoMethodError exception."
dummy = Dummy.new
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)

class Dummy
def method_missing(m, *args)
puts "There's no method called #{m} here -- so method_missing method is called."
puts " with arguments #{args}"
end
end
dummy = Dummy.new
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实现

class Finder
def find(name)
puts "find(#{name}) is called"
end

def method_missing(name, *args)
if /^find_(.*)/ =~ name.to_s
return find($1)
end
super
end
end

f = Finder.new
f.find("Something")
f.find_by_last_name("Shin")
f.find_by_title("Technology Architect")

define_method

• The define_method defines an instance method in the receiver.

define_method 定义一个实例方法在接收者。

define_method(symbol, method) => new_method
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

class Love
define_method(:my_hello) do |arg1, arg2|
puts "#{arg1} loves #{arg2}"
end
end

love = Love.new
love.my_hello("Sang Shin", "Young Shin")
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: