Ruby 大家平时习惯怎么使用属性?

fsword · 2013年07月19日 · 最后由 fsword 回复于 2013年08月26日 · 3073 次阅读

对于如下属性定义:

class A
  attr_accessor :x
end

在使用中有两种写法——

  • 写法一

    class A
    def hello m
    ...
    self.x = m
    ...
    end
    def hello2
    ...
    dosomething self.x
    ...
    end
    end
    
  • 写法二

    class A
    def hello m
    ...
    @x = m
    ...
    end
    def hello2
    ...
    dosomething @x
    ...
    end
    end
    

    后者更短些,但是依赖了 attr_accessor 的实现,大家一般倾向于怎么写?

短的吧,为何介意这个?

attr_accessor :x 多简单啊,何必那么复杂呢,除非要在复制或取值的时候实现一些动作

好像可以写成 attr :x

#2 楼 @huacnlee 我说的是如何使用,原帖有误导性,我修改一下

第二个方法要显示写一堆实例变量。恶心。

2,为啥说后者依赖 attr_accessor?

#6 楼 @jjym 不是依赖 attr_accessor,而是依赖了它的具体实现,如果有一天不这么实现(或者有人想拦截下来做点啥事)就抓瞎了

#3 楼 @chenge 后面是否必须要指定 true false 的可写可读权限>?

#8 楼 @staticor true 表示可写。多了个参数。

看老外说,不推荐用 attr。没有文档化。还是用 accessor。

我是觉得单词有点长,要是用 init,attr 就好了。

attr_reader 和 @something =

attr_reader 的好处是可以做成类似 perl bareword 的特性 重新加载

#11 楼 @knwang 那内部读取属性的时候呢,你一般习惯用 @x 还是用 self.x

#12 楼 @fsword 有 attr_reader x 就可以了啊

#13 楼 @knwang 这是声明或者说定义,我说的是使用

楼上几乎全部都像华顺一样误解了,是我表达有问题吗?

#14 楼 @fsword 就是 x 就可以了啊,比如 puts x

#16 楼 @knwang 那倒也行,不过因为赋值不能这样(否则是局部变量),导致写法上会有不一致的感觉

我觉得你多虑了,一个类的内部修改起来能有多麻烦?

再说“如果有一天”这种句式都有预先设计的嫌疑。我习惯考虑当下需要什么,然后选择最简单直接的方式。

我也理解错了么?

#19 楼 @yuan 属性方法是为了隔离,算是个编程契约吧,未来是否改变实现姑且不论,拦截 setter/getter 方法还是很有可能的

#20 楼 @fsword 那我还是会在真的需要拦截的时候加上。我只是觉得在一个类的内部范围内修改对本身属性的访问方式不是什么大事,没有多麻烦,除非这个类写得很大很复杂。

不过这个问题似乎也是各人有各人的喜好,我记得好像 Kent Beck 比较喜欢无论什么时候在内部都用自封装字段,Martin Fowler 则是习惯直接操作实例变量,有必要的时候再封装。

#7 楼 @fsword http://apidock.com/ruby/Module/attr_accessor API 上都写了行为。。应该不会改变了,而且绝对不可能改变 attr 应该是对外部来说的,而且类内部需要看具体逻辑来调用是 attr 还是 variables(两者相同时我会调用 variables) 就算有人拦截下来做些事情,也要根据具体的逻辑来看内部的操作是否也需要做这些事情

Premature optimisation is the root of evil

速度不是问题,读写属性方法有特化指令去优化的 但拦截是 corner case, 没必要优先考虑

问题是:你要不要暴露这个属性,不要就 @, 要就两种写法没区别。如果不能确定一个东西该有还是不该有,那就先删掉它。

忍不住回一句:为什么我一看楼主的问题,立刻就知道楼主希望表达的问题是什么呢?

@fsword , 我想说:accessor 的作用,就是让你用的,无论内外。默认的 accessor 就是精确的等价于实例变量的访问器,它的行为又怎么会变呢?

但是使用 accessor 而不是 实例变量的好处是不言而喻的。可见性就不说了,将来你可以轻松的添加逻辑,而不用在将来需要的时候才改写源代码 (例如:之前用 @x, 后来加了逻辑,才开始使用 accessor), 对于类似 C# 这样的静态语言,还有另一个好处就是:你只需编译实现 accessor 逻辑的代码,而所有引用属性的部分,都无需重新编译,多好?

还有,敏捷开发那本书也是推荐访问器方式的。

不过,如果从一开始设计,就根本没打算从外部访问,以上好处就全没有了,直接使用实例变量也未尝不可,不过,如果你的一个方法中用到了实例变量,你该如何写单元测试?你无法轻松的 stub 这个实例变量,最终,你可能还得换成访问器。

#17 楼 @fsword

我一般还是不写 self 的,但是,如果是方法内本地变量,我自己有个小小的约定,加一个 _ 前缀,所以也没什么问题。_x 才是变量,x 肯定是访问器方法。不过碰到写访问器方法调用,只能加 self 了。

#26 楼 @zw963 恩,看了大家的说法,我现在还是尽量用访问器来操作,避免用@变量,like this

self.x = blablabla
dosomething x
需要 登录 后方可回复, 如果你还没有账号请 注册新账号