Ruby的符号足以让很多初学者迷惑上一段时间,看过本章节后,或许会解开你心中的疑惑。
在Ruby中,一个符号是就是一个Symbol类的实例,它的语法是在通常的变量名前加一个冒号,如 :my_sy
Ruby的符号像一个字符串,因为它内部表现形式是一个字符序列。而与字符串不同的是,每个符号的实例只有一个。看下面的例子: array = ["foo", "foo", "foo", :foo, :foo, :foo]
建立这个数组后,内存中将有三个内容为"foo"的字符串对象,而只有一个:foo对象。
一个符号有它唯一对应的一个整数值,可以用to_i来获取它。
符号常用的地方是用它来代表变量名或者方法名: class SomeClass attr_accessor :whatever end
与上面程序对等的程序如下: class SomeClass def whatever @whatever end def whatever=(val) @whatever = val end end
你可能会问,为什么不用字符串来表示呢?其实,字符串也是可以的: attr_reader :alpha attr_reader "beta" # 也是合法的
那它们的区别在哪里?某种意义上来说,是为了提高程序性能,节省内存吧。
有的人说,"符号就如同不可变的字符串",从它的行为上来说,可能是对的。但是,Symbol并是是继承至String,而且,与字符串相关 的那些典型操作方法,Symbol也不一定有,也不需要有。
符号不一定看起来是像变量一样,它也可以这样: sym1 = :"This is a symbol" sym2 = :"This is, too!" sym3 = :")(*&^%$" 你可以用这样奇怪的符号来定义实例变量名或方法,你可以使用诸如send或instance_variable_get来获取它们的引用。虽然是可行的, 但请尽量不要使用这么奇怪的符号。
用Symbol作为枚举 ========================================== 像Pascal或版本稍晚的C语言,都存在enum这种类型。Ruby不能正真的拥有这样的类型,因为它没有类型检查。但使用Symbol可以用来产生 这样的效果: North, South, East, West = :north, :south, :east, :west
用Symbol作为元数据 ========================================== 通常我们使用捕获异常的方式来处理错误,避免使用老式的返回代码的方式。但是,如果你想用老式的方式,还是可以的。像nil就是这样一个元数据。 我们通常可以这样使用(因为符号是全局的,所以在之后的整个程序中,都可以使用这些符号来作为元数据): str = get_string case str when String # Proceed normally when :eof # end of file, socket closed, whatever when :error # I/O or network error when :timeout # didn't get a reply end
Symbols, Variables, Methods ========================================== Symbol最常用的地方就是我们熟知的定义属性了: class MyClass attr_reader :alpha, :beta attr_writer :gamma, :delta attr_accessor :epsilon # ... end 这里的方法,如attr_accessor,它以传入的符号来确定实例变量的名称,以及读写属性的方法的名称,但这不代表所有的情况 (即总是会自动精确匹配符号和实例变量的名称),例如,当使用instance_variable_set方法的时候,符号和实例变量名必须 精确给出: sym1 = :@foo sym2 = :foo instance_variable_set(sym1,"str") # 正常,匹配到@foo instance_variable_set(sym2,"str") # 错误
不过,记住,在这些地方不一定要使用符号,可以用字符串来替代。
转换Symbol ============================================ Symbol和字符串之间可以互相转换,使用to_s和to_sym来实现: a = "foobar" b = :foobar a == b.to_str # true b == a.to_sym # true
|
请发表评论