Ruby和面向对象技术

Ruby和许多极为流行的编程语言都是面向对象的。多数的面向对象编程语言,每个对象都是一个样例或者既定类的实例以及独立对象的行为。

一、创建一个通用对象

创建一个通用对象

ruby 复制代码
obj = Object.new

定义通用对象的行为

ruby 复制代码
def obj.talk 
    puts "I am an object"
    puts "(Do you object?)"
end

定义带参数的方法

ruby 复制代码
def obj.c2f(c)
    c * 9.0 / 5 + 32
end

任何方法的返回值与方法执行中最后一个表达式的计算值相等

Ruby提供了一个关键字明确地定义了返回值:return,这个关键字地使用通常是可选的,但是多数程序员都喜欢用它,因为它使隐式的返回值表达式变得显而易见。

ruby 复制代码
def obj.c2f(c)
    return c * 9.0 / 5 + 32
end

假如需要返回多个值则必须使用它,这些值会自动被包装为一个数组。

二、制作一个对象

一张入场券是一个常见的对象,且有一组众人熟知的属性和行为。这里将从一个较高的视角来看待一个如入场券般的Ruby对象能做什么以及该对象对自身的理解。

创建一个ticket.rb

ruby 复制代码
ticket =  Object.new

def ticket.date
    "01/02/03"
end
def ticket.venue
    "Town Hall"
end
def ticket.event
    "Author's reading"
end
def ticket.performer
    "Mark Twain"
end

def ticket.seat
    "Second Balcony, row J, seat 12"
end

def ticket.price
    5.50
end

这个马克吐温的入场券是一个简单的例子,但是它包含了一些Ruby编程的重要流程和原则。这个最重要的经验就是:程序完成任何有用事情的信息都必须存储于对象之中。ticket对象拥有这些信息,通过方法的调用可以请求ticket对象返回信息

查询对象

ruby 复制代码
print "This ticket is for: "
print ticket.event + ", at "
print ticket.venue + ", on "
puts ticket.date + "."
print "The performer is "
puts ticket.performer + "."
print "The seat is "
print ticket.seat + ", "
print "and it costs $"
puts "%.2f." % ticket.price

通过字符串插值缩短查询代码:

ruby 复制代码
puts "This ticket is for: #{ticket.event}, at #{ticket.venue}" + 
    "The performer is: #{ticket.performer}." + 
    "The seat is: #{ticket.seat}, " + 
    "The it costs #{"%.2f." % ticket.price}"

无论在插值运算符中的内容是什么,他都能被分步求值,求值的结果会被插入字符串中。

用方法表达布尔状态

ruby 复制代码
def ticket.avai_status
    "sold"
end
def ticket.avai?
    false
end

if ticket.avai?
    puts "You are in luck!"
else
    puts "Sorry--that seat has been sold."
end

注意方法avai?以问号结尾

三、对象的原生行为

就算是新创建的对象也不会是一块白板。只要对象创建并存在,它就能响应一组消息。

输入以下命令可以查看原生方法的列表:

bash 复制代码
Object.new.methods.sort

这些原生方法中的一小部分是非常普遍和非常有用的。

1、用object_id表示唯一标识对象

在Ruby中,每个对象都有一个和它唯一关联的ID编号。可以通过请求一个对象的object_id获得一个对象的ID,使用如下类似的代码。

ruby 复制代码
obj = Object.new
puts "The id of obj is #{obj.object_id}."
str = "Strings are objects too, and this is a string!"
puts "The id of the string object str is #{str.object_id}."
puts "And the id of the integer 100 is #{100.object_id}"

运行这段代码可以看到

bash 复制代码
The id of obj is 60.
The id of the string object str is 80.
And the id of the integer 100 is 201

在尝试确定两个对象是否相等的时候,每个对象都拥有一个唯一的ID编号是很有用的,可以通过判断object_id是否相等而判断两个对象是否相等。

ruby 复制代码
a = Object.new
b = a
puts "a's id is #{a.object_id} and b's id is #{b.object_id}"

运行之后可以看到a和b的对象id是相同的。

2、用respond_to?方法查询对象的能力

Ruby对象响应消息。在程序运行期间的不同事件点,依赖于对象和为对象定义的各种方法,一个对象可能会响应指定的消息,也可能不会。所以可以使用respond_to?方法判断一个对象是否有某种方法。

ruby 复制代码
if obj.respond_to?("talk")
    obj.talk
else 
    puts "Sorry, the object doesn't understand the 'talk' message"
end

该方法时自省或者反射的一个例子,这两个词指的是可以在程序运行期间进行状态检测。Ruby提供了许多用于自省机制的工具。使用methods方法测试对象,是另一种自省和反射的技术。

3、用send方法发送信息给对象

如果希望从键盘输入合适的查询词组(venue、performer等),就能从ticket对象中得到信息,则需要把如下代码添加到已有的程序中:

ruby 复制代码
print "Information desired: "
request = gets.chomp

该行代码可以从键盘中获取一行输入。这样可以使用双等号比较符测试两个不同的输入值,它会基于对象自身的内容对字符串进行比较,然后调用与值匹配的方法。

ruby 复制代码
if request == "venue"
    puts ticket.venue
elsif request == "performer"
    puts ticket.performer
......

尽管如此,还是不得不继续编写整个入场券的属性列表,但那变得有些冗余了。

这里还有一个可选的方案:给ticket对象直接发送对应的词语。按如下方式替换前面例子里的代码:

ruby 复制代码
if  ticket.respond_to?(request)
    puts ticket.send(request)
else 
    puts "No such information available"
end

这个版本中使用了send方法作为ticket对象获得消息的通用入口。这样可以避免整个可能的请求清单,并由处理ticket对象的消息执行该消息,以取代检查ticket对象所具有的能力。

还可以使用__send__或者public_send代替send,__send__方法比普通send更安全,而public_send不能访问私有方法。

四、方法参数

在编写方法的时候允许传递任意数量的参数,在单独的方法参数名称前使用一个*即可:

ruby 复制代码
def obj.multi_args(*x)
    puts "I can take zero or more arguments!"
end

符号*x表示在调用方法的时候,可以提供任意数量的参数。变量x被分配一个对应任意参数的数组。可以在稍后使用数组每次测试其中的一个。

一般情况下,参数都是变量的引用,如果不想变量发生变化,可以传入s.dup复制了一个对象。

ruby 复制代码
def change_string(s)
    s.replace("New String!")
end
s = "Original String"
change_string(s)
change_string(s.dup)

还可以冻结一个变量,冻结后不能再对这个变量发生改变

ruby 复制代码
s.freeze
相关推荐
来一杯龙舌兰2 天前
【RabbitMQ】RabbitMQ保证消息不丢失的N种策略的思想总结
分布式·rabbitmq·ruby·持久化·ack·消息确认
明志-5 天前
RabbitMQ 工作模式使用案例之(发布订阅模式、路由模式、通配符模式)
分布式·rabbitmq·ruby
Agnoni7 天前
RabbitMQ消息队列的笔记
java·笔记·spring cloud·rabbitmq·ruby
飞的肖8 天前
RabbitMQ 安装、配置和使用介绍 使用前端js直接调用方式
开发语言·javascript·ruby
破局缘8 天前
apt文件问题ruby.list文件
开发语言·windows·ruby
Elastic 中国社区官方博客10 天前
如何将你的 Ruby 应用程序从 OpenSearch 迁移到 Elasticsearch
大数据·开发语言·数据库·后端·elasticsearch·搜索引擎·ruby
PGCCC11 天前
【PGCCC】 pg_query 6.0:使用 Postgres 自己的解析器解析、反解析和规范化 SQL 查询的 Ruby 库
数据库·sql·ruby
爱lv行12 天前
使用 rbenv 切换 Ruby 版本
开发语言·前端·ruby
信徒_14 天前
Rabbitmq 镜像队列
分布式·rabbitmq·ruby
姜西西_17 天前
RabbitMQ核心概念及工作流程 + AMQP
分布式·rabbitmq·ruby