- 浏览: 1384066 次
- 性别:
- 来自: 陕西.西安
文章分类
最新评论
-
dare_:
经过试验 设置之后反而更慢没有调用ensureCapacity ...
ensureCapacity()方法提高ArrayList的初始化速度 -
wangchao9053:
[flash=200,200][url][img][list] ...
Only the original thread that created a view hierarchy can touch its views的相关 -
cyb504:
考虑将rb文件代码隐藏:我先使用命令jrubyc将所有rb文件 ...
Ruby学习十 JRuby中调用java代码 -
4562xse3460:
大哥,您这个写反了,差点误导我,我觉得看着就不对。百度第一条就 ...
portrait表示纵向,landscape表示横向 -
yin138:
portrait是肖像画,即竖屏,landscape是风景画, ...
portrait表示纵向,landscape表示横向
http://www.ibm.com/developerworks/cn/opensource/os-cn-rubysbl/
Ruby 是一个强大的面向对象脚本语言(本文所用 Ruby 版本为1.8.6),在 Ruby 中 Symbol 表示“名字”,比如字符串的名字,标识符的名字。
创建一个 Symbol 对象的方法是在名字或者字符串前面加上冒号:
:foo :test |
:”
abc”
:”I am a boy” |
你可能会问,字符串就是字符串,干吗还有字符串的名字?这是因为在 Ruby 中字符串也是一种对象,即 String 对象。无论其结构还是操作和 Symbol 对象都是不同的。
在 Ruby 中每一个对象都有唯一的对象标识符(Object Identifier),可以通过 object_id 方法来得到一个对象的标识符。我们来看看 Symbol 对象和 String 对象的差别:
irb(main):001:0> puts :foo.object_id 327458 => nil irb(main):002:0> puts :foo.object_id 327458 => nil irb(main):003:0> puts :"foo".object_id 327458 => nil irb(main):004:0> puts "foo".object_id 24303850 => nil irb(main):005:0> puts "foo".object_id 24300010 => nil irb(main):006:0> puts "foo".object_id 24296170 => nil |
可以看到,前三行语句中的 :foo (或者 :"foo")都是同一个 Symbol 对象,其 object id 为327458,而后三行中的字符串”foo”都是不同的对象,其 object id 依次为24303850、24300010、24296170。
可见,每个 String 对象都是不同的,即便他们包含了相同的字符串内容;而对于 Symbol 对象,一个名字(字符串内容)唯一确定一个 Symbol 对象。
值得注意的是创建 Symbol 对象的字符串中不能含有’\0’字符,而 String 对象是可以的。
irb(main):001:0> :"fo\0o" SyntaxError: compile error (irb):1: symbol cannot contain '\0' from (irb):1 irb(main):002:0> :"foo\0" SyntaxError: compile error (irb):2: symbol cannot contain '\0' from (irb):2 irb(main):003:0> puts "foo\0".object_id 24305140 => nil irb(main):004:0> puts "fo\0o".object_id 24301000 => nil irb(main):005:0> |
除了可以采用一般的字符串,还可以使用操作符(例如+, -, *, /),变量,常量,方法甚至类的名字来创建 Symbol 对象,例如:+就是一个合法的 Symbol 。实际上,在 Ruby 内部操作符、变量等名字本身就是作为 Symbol 处理的,例如当你定义一个实例变量时, Ruby 会自动创建一个 Symbol 对象,例如 @test 对应为 :@test 。
class Test attr_accessor :test end |
这个类定义了一个具有读写方法的实例变量 @test 。实际上 Ruby 创建了两个 Symbol ,一个是实例变量的 symbol :@test ,另一个是 :test 。那如果使用字符串对象 ”test” 作为参数呢?也可以,仍然会创建两个 symbol ,:test 和 :@test ,为什么还会创建 :test 呢?这是和Ruby的实现相关的(至少Ruby1.8.6里是这样)。
注意,类变量 @@test 和实例变量 @test 对应的 Symbol 显然是不同的。记住:名字相同,则Symbol 相同。
class Test puts :Test.object_id Test = 10 puts :Test.object_id def Test puts :Test.object_id end end Test.new.Test |
运行结果
224298 224298 224298 |
名字不同, Symbol 不同
class Test puts :Test.object_id @@test = 10 puts :@@test.object_id def test puts :test.object_id @test = 10 puts :@test.object_id end end t =Test.new t.test |
运行结果
224298 288068 79858 288108 |
第一个例子里,类名、常量名和方法名都是 Test ,因此相应的 Symbol 对象都是 :Test 。不用担心, Ruby 可以很好区分它在不同上下文中到底表示什么。当然这并不是一个好的编程风格,但对于理解 Ruby 的 Symbol 还是有帮助的: Symbol 表示一个名字,仅此而已。
Symbol 对象一旦定义将一直存在,直到程序执行退出。所有 Symbol 对象存放在 Ruby 内部的符号表中,可以通过类方法 Symbol.all_symbols
得到当前 Ruby 程序中定义的所有 Symbol 对象,该方法返回一个 Symbol 对象数组。由于 Symbol 比较多,你可以 dump 到文件中来查看。
irb(main):001:0> Symbol.all_symbols.size => 4047 irb(main):002:0> Symbol.all_symbols[0..9] => [:@level_notifier, :ppx, :msg_dn, :version, :secs, :@user, :pos, :socketpair, :TkENSURE, :HTTPAccepted] irb(main):003:0> File.open("sym", "w") do |file| file.puts Symbol.all_symbols end => nil |
Symbol 对象和 String 对象是完全不同的东西,对象标识符很明确的说明了这一点。除此之外,我们还可以从两种对象的方法上区分。
查看 Ruby 库参考,你会发现 String 类有非常多的方法,包括 Mixed-in 方法(Ruby中一个类通过 include 其他模块而得到的方法,实现多重继承的效果)、类方法和实例方法;而 Symbol 类只有一个类方法 all_symbols
和7个实例方法。
例如,可以通过 []=
方法改变 string 的内容,而 symbol 则不行:
irb(main):001:0> s="test" => "test" irb(main):002:0> s[0]='1' => "1" irb(main):003:0> puts s 1est => nil irb(main):004:0> sym=:test => :test irb(main):005:0> sym[0]=1 NoMethodError: undefined method `[]=' for :test:Symbol from (irb):5 irb(main):006:0> |
虽然 Symbol 和 String 是不同的对象,但它们之间关系很密切。 Ruby 提供了方法在 Symbol和 String 之间转换。
使用 to_s 或 id2name 方法将 Symbol 转化为一个 String 对象:
irb(main):001:0> :test.id2name => "test" irb(main):002:0> :test.to_s => "test" irb(main):003:0> :"I am a boy".to_s => "I am a boy" |
注意,每个 String 对象都是唯一的,因此对一个 Symbol 调用多次将产生多个 String 对象。
除了在字符串前面加冒号,还可以使用 to_sym 或 intern 方法将 String 转化为 Symbol ,如果该 Symbol 已经存在,则直接返回。
irb(main):001:0> var1 = "test".to_sym => :test irb(main):002:0> var2 = "test".intern => :test irb(main):003:0> var1 == var2 => true irb(main):004:0> |
正如前边提到的, Ruby 内部一直在使用 Symbol ,比如 Ruby 程序中的各种名字,Symbol本质上是 Ruby 符号表中的东西。使用 Symbol 处理名字可以降低 Ruby 内存消耗,提高执行速度,这点我们在下一篇文章中会看到。
那么 Symbol 对我们有什么用呢?当然也是内存。使用 String 的开销太大了,因为每一个String 都是一个对象。想想前边的例子,一个字符串每出现一次 Ruby 就会创建一个 String 对象。
通常来讲,当你面临 String 还是 Symbol 的选择时,可以参考以下标准:
- 如果使用字符串的内容,这个内容可能会变化,使用 String
- 如果使用固定的名字或者说是标识符,使用 Symbol
那么什么时候我们会用到名字呢?很多时候都会,比如枚举值、关键字(哈希表关键字、方法的参数)等等
哈希表是 Symbol 应用最为广泛的地方。
在ruby中,哈希和数组类似,一个哈希表是一系列 key/value 对的集合,只不过它的 key 取值范围更广泛,可以是任何对象,比如正则表达式。但通常我们都会取有意义的 key ,比如 String、Symbol 。
下面这个哈希表表示按城市分类的一些机器的集合。
hosts{ 'beijing' => 'machine1', 'shanghai' => 'machine2', 'guangzhou' => 'machine3', 'tianjin' => 'machine4', 'shenzhen' => 'machine5' } |
如果要引用 beijing 的机器,使用 hosts['beijing'] 。但如果我们程序中要频繁引用哈希表中 value ,这样就不大好了,因为 Ruby 对每一次字符串引用都会生成一个 String 对象,累积下来这个开销是相当大的。
我们完全可以使用 Symbol ,因为对于这些 key 来讲,我们用的就是名字而已,例如下面hosts[:beijing] |
使用 Symbol 作为 key
hosts = { :beijing => 'machine1', :shanghai => 'machine2', :guangzhou => 'machine3', :tianjin => 'machine4', :shenzhen => 'machine5' } |
哈希参数
通常我们定义的函数的参数的个数和顺序是写死的,调用函数的时候要确保参数的个数、顺序匹配,有时候这样很不方便,使用哈希参数可以解决这个问题。
ROR 中就大量地运用这种方式,也许你已经看到了,到处都是 Symbol 和哈希。比如:
link_to 'Show', :action => 'show', :id => product add_column :products, :price, :decimal, :precision => 8, :scale => 2, :default => 0 |
使用哈希参数的方法可以如下定义,前半部分为固定参数,后面为可变参数,或者干脆全采用哈希参数:
def my_method(para1, …, options={}) #your code end def my_method(options={}) #your code end |
如果你希望设定一些默认参数,并允许调用者更改这些参数,可以使用哈希对象的 merge! 方法
hsh.merge!( other_hash )
。该方法将
other_hash
里内容加到
hsh
中,如果other_hash
与
hsh
有重复的
key
,则
key
在
other_hash
中的
value
覆盖
hsh
中对应
key
的
value
。
class Test def my_method(opts={}) default_opts={:arg1 => 10, :arg2 => "abc"} default_opts.merge!(opts) default_opts.each{|key,value| puts "#{key} is #{value}"} end end t = Test.new t.my_method :arg1=>5, :arg3=>"def" |
运行结果
arg1 is 5 arg2 is abc arg3 is def |
在 Rails 中,对 hash 类进行了扩展,可以使用 reverse_merge! 方法来达到上述效果。该方法在 ActiveSupport::CoreExtensions::Hash::ReverseMerge 中定义。Rails 甚至还提供了 assert_valid_keys 方法,对传递进来的哈希表的 keys 进行合法性检验。
Perl 说,条条大路通罗马。在 Ruby 中也是这样的,也许你会发现更好的应用 Symbol 和哈希的方法。
下篇文章我们将深入 Ruby 内部来看看 Symbol 的样子。
- 在 Ruby 的官方网站可以得到各种 Ruby 信息:下载、文档、社区
- Ruby on Rails(ROR) 的官方网站,你可以浏览 Rails 的方方面面:API、CoreLib等
- 在 RubyForge 找到更多 Ruby 开源项目。
- 一个不错的Ruby 学习站点,有一些关于 Symbol 的内容。
- 阅读 developerWorks 上的文章“使用Ruby on Rails 快速开发Web 应用程序”
- “Programming in the Ruby language” (developerWorks) Ruby 编程简介。
- Programming Ruby: The Pragmatic Programmer's Guide 的在线版本。
<!-- CMA ID: 293468 --><!-- Site ID: 10 --><!-- XSLT stylesheet used to transform this file: dw-article-6.0-beta.xsl -->
发表评论
-
rsync参数详解、利用ssh、rsync 实现数据的定时同步
2012-09-11 14:52 1733http://colderboy.blog.51cto.com ... -
putty
2011-12-02 10:50 1125http://www.iteye.com/topic/5606 ... -
haml
2011-12-01 22:53 1147http://aideehorn.iteye.com/blog ... -
ruby 生成随机数 和 随机字符串
2011-11-30 22:42 3546ruby 生成随机数 和 随机字符串 1,ra ... -
ruby and watir学习之_Hash 类
2011-11-20 17:53 1667http://www.cnblogs.com/zhangfei ... -
gem相关命令使用
2011-11-19 00:01 2859http://www.cnblogs.com/orez88/a ... -
Rails,启动-重要
2011-11-17 09:59 1807http://www.blogjava.net/sshwsfc ... -
使用 RSpec 进行行为驱动测试,配置分析
2011-11-11 13:21 1600http://huangzhimin.com/ < ... -
ruby的class与module的区别
2011-11-07 10:04 2384http://blog.163.com/rettar@126/ ... -
ruby invalid multibyte char (US-ASCII)
2011-11-05 01:57 4707要加上: # encoding: utf-8 一般要 ... -
File.split(pathname)
2011-11-05 01:42 2270http://www.kuqin.com/rubycndocu ... -
Ruby怎样获取操作系统的Name
2011-11-05 01:30 1299http://bbs.chinaunix.net/thr ... -
Ruby String#unpack
2011-10-31 11:34 1314http://fuliang.iteye.com/blog/6 ... -
ruby环境变量的文件读取形式
2011-10-31 11:29 1866http://blog.csdn.net/normallife ... -
Ruby学习九 排序 sort
2011-10-26 20:06 3587h = ['1','10','11','2','4']A. p ... -
关于rails插件will_paginate的配置和用法
2011-10-26 15:56 4382http://selfcontroller.iteye.com ... -
ruby 中的 && ,|| ,!! (转)
2011-10-26 14:59 970http://selfcontroller.iteye.com ... -
Ruby中 respond_to? 和 send 的用法 .
2011-10-26 14:19 5374http://selfcontroller.iteye.com ... -
ruby 在线正则表达式 编辑器
2011-10-25 09:22 1758http://www.rubular.com/ -
ruby-Jruby,Xruby 转
2011-10-25 09:22 894ruby-Jruby,Xruby 2009年06月21 ...
相关推荐
《深入理解openGauss Symbol:探索3.0.0版本的细节》 openGauss,一个开源、高性能的关系型数据库管理系统,旨在为大数据时代提供可靠的数据存储与处理解决方案。openGauss-3.0.0-CentOS-64bit-symbol.tar.gz 文件...
《深入解析openGauss Symbol:基于openGauss-3.0.0-openEuler-64bit-symbol.tar.gz》 openGauss是一个开源的关系型数据库管理系统,由华为公司主导开发,旨在提供高性能、高可用性、高安全性的企业级数据库解决方案...
symbol字体键盘对照表,直接打出各种希腊字母,不需要公式编辑器,在word里面对照symbol字体直接打出即可
Symbol 条码枪 LS4208 使用手册 Symbol LS4208 是一款高性能的条码枪,广泛应用于零售、物流、医疗、制造等行业。本手册提供了 Symbol LS4208 的使用指南,帮助用户快速上手使用该设备。 1. Symbol LS4208 概述 ...
"Symbol"是摩托罗拉解决方案公司的一个品牌,主要生产工业级条形码扫描器、移动数据终端等设备,这些设备在零售、物流、医疗等领域广泛应用。"MC系列"是Symbol推出的一系列坚固型移动计算机,它们配备有各种操作系统...
symbol Italic 希腊字母 斜体 希文 斜体 希腊 斜体 symbol 斜体
"字体-Symbol-Tiger-Expert"这个主题聚焦于一种特定的字体,用于解决在Windows 7系统中因字体文件缺失而导致数学符号无法显示的问题。Symbol字体是一种特殊的符号字体,通常包含了各种数学、化学和科学符号,以及...
什么是Symbol JavaScript标准中规定对象的key只能是 String 或 Symbol 类型,区别在于 String 类型的key可以重复而 Symbol 类型的key是唯一的。Symbol 的本质是表示一个唯一标识。每次创建一个Symbol,它所代表的值...
* Caps Lock 覆盖:键盘将忽略 Caps Lock 按键的状态,因此,条码中的一个大写“A”被传送作为一个大写“A”,无论键盘的 Caps Lock 键的状态是什么。(默认值) 1.2 通过 RS-232 与主机端口连接 * RS-232 主机...
标题与描述中的关键词“symbol LS2208”指向了由Symbol Technologies公司制造的一款非常流行的条形码扫描器。这款扫描器在零售业、仓库管理、物流和其他需要快速准确读取条形码的行业中被广泛使用。以下是关于symbol...
《symbol-4278设置手册》是一份详尽的指南,主要针对Symbol公司的4278系列条形码扫描器的配置与操作。Symbol Technologies是条形码和无线数据通信技术领域的领导者,其产品广泛应用于零售、物流、医疗保健等众多行业...
### Symbol MC1000 开发手册核心知识点解析 #### 一、版权与许可声明 在文档开头,Symbol Technologies, Inc. 对该手册进行了明确的版权保护声明,并规定了使用条款: - **版权归属**:所有版权归属于Symbol ...
标题 "wps_symbol_fonts.zip" 暗示了这是一个针对WPS Office软件的补丁或资源包,专门解决在Linux操作系统环境下WPS缺少特定字体的问题。这个压缩包包含的字体文件,可能是为了确保WPS在Linux系统中能够正确显示某些...
解决 error LNK2001: unresolved external symbol 在编译VC项目时,经常会遇到error LNK2001: unresolved external symbol的错误,这个错误是由于缺少某些库文件而引起的。在这里,我们总结了三种常见的情形,并...
"SYMBOL FACTORY 图符集" 是一个专为制作自动化方案设计的资源库,其中包含了大量的工业图符,这些图符对于理解和构建自动化系统来说至关重要。这个图符集旨在提高工作效率,帮助工程师们快速、清晰地绘制出各种控制...
"Symbol Factory 2.0.138"是一款专为工业控制(Industrial Control)领域设计的图形库软件,它的主要功能在于提供丰富的图形资源,帮助用户快速创建和编辑各种工控设备、仪器仪表的图标和图形。这款软件的一大特点是...
"SymbolTypeViewer"是一款专为IT专业人士设计的工具,主要用于查看和分析符号类型。这款软件在调试和排错过程中尤其有用,因为它可以帮助用户理解和解析内存中的符号信息,这对于理解代码执行流程和诊断问题至关重要...
《工控图库工具symbol-factory-2.0详解及应用》 在自动化工程和工业控制领域,图形化界面的设计与构建是至关重要的。Symbol Factory 2.0是一款专为工控系统设计的图库工具,它为组态王软件提供强大的辅助功能,帮助...
在通信系统的发展历程中,载波(Carrier)与符号定时恢复(Symbol Timing Recovery)技术扮演了极其关键的角色。它们共同确保了数字信息能够高效、准确地在复杂的通信网络中传输和接收。要深入理解这两个概念,首先...