Ruby中的一切都是动态的,例如,我们可以在程序运行时,动态的添加方法,类等。前面我们已经看到了Ruby的动态特性,例如:给单个对象添加方法,重新打开类等。
如果熟悉Rails,就知道ActiveRecord提供基于数据库表的字段名的方法。每一个字段都有一个方法,这个就依赖于Ruby的动态特性。
一、单例类的位置
我们可以为一个对象定义只属于自己的方法
obj=Object.new
def obj.say
puts "Hello World"
end
obj.say #输出 Hello World
那么单例方法定义在哪里呢?Ruby把单例方法定义在单例类(singleton class)中.每一个对象实际上都有两个类:
对象调用的方法就是定义在这两个类中的方法,以及祖先类和混含模块中的方法,对象可以调用它所属的类的实例方法,也可以调用单例类中的方法。单例类是匿名的,他们是类对象的实例(Class类的实例),但他们是自动生成且没有名字
str="Hello World"
class<<str
def bye
self+", bye"
end
end
puts str.bye
输出 "Hello World, bye"
在方法查找上,单例方法是最先找到的。
二、eval方法
这个和其它很多语言一样,具有在运行时执行以字符串形式保存代码的的功能。
1.直接执行代码
2. 运行时提供方法名的例子
print "Greeting Method:"
m=gets.chomp
eval("def #{m};puts 'Hello'; end")
eval(m)
输出:Hello
如果输入hi, eval求职的字符串是 def hi; puts 'Hello'; end
三、eval的危险性
eval很强大,但是它也潜在着危险,这个有点像sql注入
假如,上面我们输入的不是hi而是下面的内容
hi; end; system("rm -rf /*"); #
eval求值以后是这样的
def hi; end; system("rm -rf /*"); # puts 'Hello'; end
求值的结果是:#后面的所有内容会被作为注释忽略掉。使用system命令试图删除系统所有文件
Ruby有一个全局变量$SAFE(取值范围是0到4)、以获取对如非法写文件这一类危险的防护。
四、instance_eval
该方法把self变为instance_eval调用的接收者,对字符串或代码块进行求职
p self
a=[]
a.instance_eval(p self)
输出:
main
[]
instance_eval常用于访问其它对象的私有数据,特别是实例变量
class C
def initialize
@a=1
end
end
c=C.new
c.instance_eval {puts @a}
五、class_eval
class_eval可进入类定义体中
c=Class.new
c.class_eval do
def some_method
puts "created in class_eval"
end
end
c=c.new
c.some_method
利用class_eval可以访问外围作用域的变量。
var="test variable"
class C
puts var
end
C.class_eval {puts var}
变量var在标准的类定义体的作用域之外,但是在class_eval的代码块的作用域之内
当在class_eval的块中定义一个实例方法时,又有不同
var="test"
class C
end
C.class_eval {def hi; puts var; end}
c.new.hi
# undefined local variable or method `c' for main:Object (NameError)
但我们可以使用另外一种方法
C.class_eval {define_method("hi"){ puts var}}
六、Proc对象
pr=Proc.new {puts "Hello from inside of proc block"}
pr.call
#输出: Hello from inside of proc block
1、做为闭包的Proc对象
Proc对象随身携带了它的上下文,下面上下文包含一个变量a,该变量被赋值为一个特殊的字符串保存在Proc对象中。像这样带着产生它的上下文信息的
一段代码被称为闭包。产生一个闭包就像是打包一件行李:任何时候打开行李,都包含打包进去的东西,在打开一个闭包时(通过调用它),它包含产生
它的时候你放进去的东西。
def call_proc(pr)
a="Jack"
puts a
pr.call
end
a="Tom"
pr=Proc.new {puts a}
pr.call
call_proc(pr)
#输出: Tom
# Jack
# Tom
2. Proc对象的参数
产生Proc对象时所提供的代码块可以接收参数
pr=Proc.new {|x| puts "#{x} is better man"}
pr.call("Jack")
输出:Jack is better man
七、匿名函数(lambda)
lam=lambda {puts "Hello World"}
lam.call
输出: Hello World
lambda不是Lambda类的对象,他们是Proc类的对象
lam.class
输出: Proc
和所有的Proc对象一样,lambda是闭包;他们随身携带了生成他们的局部的上下文环境
lambda生成的Proc对象和用Proc.new生成的对象之间的差别与return有关,lambda中的return从lambda返回,而Proc中的return从外围方法返回
def test_return
l=lambda {return}
l.call
puts "I am here"
p=Proc.new {return}
p.call
puts "bye"
end
test_return
输出: "I am here"
八、再论代码块
可以在方法中吧代码块转换成Proc对象,可以通过参数中最后一个变量,且必须&开头来捕获代码块
def say_block(&block)
block.call
end
say_block {puts "How are you?"}
#output: how are you?
def test_block(x,y, &block)
puts x+y
block.call
end
test_block(1,2) {puts "Hi"}
#output: 3
# Hi
也可以将Proc对象或lambda转换为代码块
def say_block(&block)
block.call
end
lam=lambda {puts "Hello world"}
say_block(&lam)
#output: Hello world
本文作者:王德水
未经同意,禁止转载
分享到:
相关推荐
松本行弘在设计Ruby时,融合了多种他所喜爱的语言特性,包括**Perl**、**Smalltalk**、**Eiffel**、**Ada**和**Lisp**,从而创造出一种结合了函数式和过程式编程特性的独特语言。他的目标是使Ruby既自然又强大,即使...
### Ruby on Rails Guides v2 - Ruby on Rails 4.2.5 #### 一、重要概念及基础假设 - **重要概念**:本指南旨在帮助读者深入理解Ruby on Rails(以下简称Rails)4.2.5版本的核心功能与最佳实践。 - **基础假设**:...
- **Ruby**:相比之下,Ruby 是一种动态类型的脚本语言,它的语法更加灵活,支持多种编程范式(包括面向对象和函数式编程)。Ruby 代码通常更简洁、易于阅读。 2. **生产力与开发效率**: - **Java**:虽然 Java ...
4. **闭包和上下文**:理解块、Proc和Lambda如何捕获并保留其定义时的上下文,是掌握Ruby高级特性的重要一步。 5. **元编程**:Ruby允许在运行时修改自身,这被称为元编程。例如,你可以动态添加方法、修改类的行为...
Ruby是一种面向对象的、动态类型的脚本语言,以其简洁明了的语法和强大的元编程能力著称,这使得它成为开发复杂逻辑应用的理想选择,比如棋类游戏。 在Ruby-chess项目中,每个棋子被表示为一个对象,它们有自己的...
Ruby是一种动态的、面向对象的解释型编程语言,因其简洁易读的语法和强大的库支持而在Web开发领域中备受青睐。开发Ruby应用的第一步是搭建合适的开发环境。推荐使用macOS或Linux作为首选操作系统,因为这些系统通常...
- **利用元编程**:利用 Ruby 的元编程能力,如模块混合(mixins)、动态方法定义等特性进行重构。 - **利用动态类型**:通过动态地修改类和对象来优化代码结构。 - **利用代码块和迭代器**:利用 Ruby 强大的迭代器...
Ruby是一种面向对象、动态类型的编程语言,由日本的松本行弘在1995年设计并开发。它强调简洁、优雅的语法,注重程序员的生产力,并提供了丰富的库和工具支持。Ruby-2.3.0是Ruby的一个版本,发布于2016年,带来了许多...
从早期的机器语言到汇编语言,再到高级语言如C、C++、Java,以及动态语言如Python、Ruby,每一步都标志着计算机科学的进步。了解这一历史脉络有助于学习者更好地把握Ruby语言在当前编程生态中的位置及其独特价值。 ...
Ruby是一种面向对象、动态类型的编程语言,以其简洁的语法和强大的功能深受开发者喜爱。Scite,全称SciTE( Scientific ...在深入学习Ruby编程的同时,掌握Scite的各种特性和设置,无疑会成为提升开发技能的重要一步。
Ruby作为一种灵活且强大的编程语言,具有以下显著特性: - **面向对象**:一切皆对象,包括基本的数据类型。 - **动态类型**:无需提前声明变量类型,增加了语言的灵活性。 - **简洁的语法**:Ruby的语法简洁明了,...
Ruby-2.5.0是Ruby编程语言的一个版本,它在2018年发布,带来了许多性能优化和新特性。这个`.tar.gz`文件是一个压缩包,它包含Ruby 2.5.0的所有源代码文件,适用于在CentOS 6.5上安装Redmine时使用。Redmine是一款...
在Ruby-2.2.5这个版本中,有以下几个重要的改进和特性: - **性能提升**:相比于之前的版本,Ruby-2.2.5在运行速度上有所优化,提高了程序执行效率。 - **更好的垃圾回收机制**:改进了垃圾回收算法,减少了内存...
3. 运行`ruby extconf.rb`来生成Makefile,这一步会根据当前的Ruby环境配置编译选项。 4. 接着运行`make`来编译C扩展。 5. 最后,运行`sudo make install`将编译好的扩展安装到Ruby的扩展目录。 在使用Ruby-FCGI时...
Ruby是一种高级、动态的、面向对象的编程语言,它的设计理念在于提供简单且高效的编程体验。Ruby以其简洁的语法和强大的面向对象特性而受到开发者的喜爱。作为解释型语言,Ruby代码可以直接执行,无需预编译步骤,这...
标题 "24_ruby_algorithm_" 暗示我们要讨论的是使用 Ruby 编程语言实现解决数学游戏“24点”的算法。在这个经典游戏中,玩家...通过对 `24.rb` 文件的分析和学习,开发者可以加深对 Ruby 语言特性和算法设计的理解。
Ruby是一种面向对象的编程语言,以其简洁和强大的语法特性而受到开发者喜爱。在Ruby中,数组是一种非常重要的数据结构,用于存储一系列有序的元素,这些元素可以是任意类型,包括整数、浮点数、字符串、布尔值甚至是...
Ruby是一种动态类型、面向对象的脚本语言,其语法简洁优雅,特别适合快速开发和原型设计。在这篇知识总结中,我们将深入探讨Ruby中的线程同步和闭包(包括Blocks、Procs、Lambdas和Methods)。 首先,让我们关注...
通过这个项目,开发者不仅能深入理解Ruby的基本语法和特性,还能锻炼到问题解决、算法设计以及代码组织等高级编程技巧。在实际操作中,你可能还需要学习如何使用版本控制工具如Git,以及如何编写清晰的文档,以便...
Ruby中的所有基本类型、代码块、函数、类和模块都是对象,而且类是开放的,支持动态添加、更新、删除成员。Ruby的singleton特性使得对象能够拥有独特的功能,便于控制服务类型;Ruby还支持mix_in模块,使得系统设计...