Ruby Ruby 的 symbol 难以理解

xautjzd · 2013年05月24日 · 最后由 iBachue 回复于 2013年05月24日 · 4107 次阅读

断断续续的自学着 ruby,看到 symbol 这块,感觉 symbol 太难理解。attr_accessor:x 相当于创建了 x 的实力变量@x,并且创建了对应的 setter 和 getter 方法。在 ruby 的源码中想找 attr_accessor 的相关实现,但是没找到。symbol 的具体作用到底是什么呢

  1. symbol 的功用等于 string
  2. 相同的 symbol 内存地址是一样的,但相同的 String 确不一定

推荐书籍 Ruby 元编程

static VALUE
rb_mod_attr_accessor(int argc, VALUE *argv, VALUE klass)
{
    int i;

    for (i=0; i<argc; i++) {
        rb_attr(klass, rb_to_id(argv[i]), TRUE, TRUE, TRUE);
    }
    return Qnil;
}

http://apidock.com/ruby/Module/attr_accessor 点 Show source

#1 楼 @edgar_wang_cn 刚才看的就是这篇,文章写的过于晦涩

#2 楼 @hysios 目前我所了解的就是节省空间,多个对象里相同的 symbol 的 object_id 一样,内存地址相同

#3 楼 @zj0713001 谢谢,我再看看,目前看的是《ruby 编程语言》

#4 楼 @zgm 谢谢,这篇文章不错,我在看另一篇http://glu.ttono.us/articles/2005/08/19/understanding-ruby-symbols,也写的相当不错,简单易理解

#5 楼 @Rei 一点不解,就是 attr_accessor 定义的 getter 和 setter 方法前边为何都带了:符号,但是实际调用时却没有。 module Mod attr_accessor(:one, :two) end Mod.instance_methods.sort #=> [:one, :one=, :two, :two=]

你要是学过 Java 的话,Ruby 的 Symbol 相当于 Java 中的 String,Ruby 中的 String 相当于 Java 中的 StringBuffer。

#10 楼 @xautjzd 这个方法对 string 和 symbol 一样对待。就好象 attr_accessor 'one' 得出的方法也不是 'one'=

def self.attr_accessor(symbol, data)
    define_singleton_method symbol.to_s+'=' do |data|
        instance_variable_set '@'+symbol.to_s, data
    end
    define_singleton_method symbol.to_s do
        instance_variable_get '@'+symbol.to_s
    end
end

我觉得我似乎写了个类的……反正类宏就大概这么回事吧……

至于 symbol:

:x.object_id == :x.object_id
=> true
'x'.object_id == 'x'.object_id
=> false

symbol 主要是用来作为一个 key,保证唯一性。其实 symbol 这个特性在 lisp 中经常会见到,lisp 中作为 key 来使用。具体借鉴理由不知道,也许是因为好用吧。

#14 楼 @vincenttone 第二个是不等吧

#16 楼 @Rei 是呀,我的意思本来是执行了就知道结果……看来我没写清楚……已经修改过来啦

symbol 是一个概念的产物,用作指代性质的标示符,和 string 完全不是一回事。比如:

process(data, once: true, condition: [:link, :video, :image])

在上面,symbol 用来告诉 process 一些具体参数和控制方式。在其他语言可以用 string,enum 等来做模拟,但是用 symbol 的方式,能够更好地表达清楚概念。

至于所有同名的 symbol 都是一个对象,不同 string 对象不同,这些都是实现细节。

一点不解,就是 attr_accessor 定义的 getter 和 setter 方法前边为何都带了:符号,但是实际调用时却没有。 module Mod attr_accessor(:one, :two) end Mod.instance_methods.sort #=> [:one, :one=, :two, :two=]

楼主这个想当然的想法我那些之前写 Python 现在写 Ruby 的同事也曾经有过 当时我仔细给他解释了 attr_accessor 的运作原理有木有 连实现这个功能的代码都给他写出来了 他才慢慢理解 这个不怪楼主 Ruby 很多设计是不太好啦 时间长了就慢慢理解了

需要 登录 后方可回复, 如果你还没有账号请 注册新账号