论坛首页 编程语言技术论坛

self.与@的区别——别被原有的思维方式误导

浏览 4236 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-06-28  
最近在学习Rails时把先前在Java中的一些习惯性思维带了过了,结果在遇到self.与@时被这种思维方式给误导了。

遇到这个问题是在使用AcriveRecord时,在修改或者新增记录时需要添加时间戳。首先使用self.posted_at=Time.now来修改字段,一切正常。后来想到在哪篇文章中好像说过self.与Java中的this差不多,这样就不自觉的把posted_at当作了实例变量处理,试了一下用@posted_at=Time.now,没有出错,但是记录的时间并没有被更新。

起初想到书上说ActiveRecord在第一次访问那个类时,将根据表结构信息,自动添加列到实例变量并增加对这些变量的访问器。似乎没有错呀,既然是实例变量不就是@吗?

用instance_values查看才恍然大悟,@attributes这个实例变量保存了各个字段的值。ActiveRecord在初始化这一个类时,添加的实例变量并不是一个数据库字段对应于一个实例变量,而是放到了@atributes里。然后添加了对各个字段的访问器。通过methods方法可以查看实例中的所有方法,可以看到有posted和posted=这两个访问器方法。

self.!=this
self.是方法调用,而不是直接访问实例变量。

从这个错误中,我也清楚了下面三种写法的区别:
1. self.id=        调用id方法。
2. @id=            直接访问实例变量
3. id=                如果前面不加self.,解释器将认为你要给一个局部变量赋值,而不会认为你是要调用id=这个方法修字段id的数据。
   发表时间:2007-06-28  
"在修改或者新增记录时需要添加时间戳"

针对这个问题,
你只需增加两个字段created_at和updated_at,类型为:datetime
无需其他设置,就能自动达到你的要求了

至于如何转化为精确的时间戳,请其他达人解答

更多魔术字段见:
http://wiki.rubyonrails.com/rails/pages/MagicFieldNames
0 请登录后投票
   发表时间:2007-06-28  
呵呵,另一个有趣的是
@name = ""
attr_writer :name
def set_name(input_name)
  name = input_name 
end

调用set_name不会对@name设值,因为Ruby认为set_name里的name是一个局部变量……
0 请登录后投票
   发表时间:2007-06-28  
楼主对self的理解不准确。self在不同的作用域具有不同的含义,《ruby for rails》专门有一章内容就是讲self的。

具体在一个类的一个方法内部使用self,那么这个self代表该类的当前对象实例,因此:self.id= 就是调用当前该类对象实例的id=()方法。此时一定要加self,否则ruby解析器优先把id解析为一个方法内部的局部变量。

0 请登录后投票
   发表时间:2007-06-28  
这些问题,R4R里面就有讲的,此书虽然罗嗦,但是还不错
0 请登录后投票
   发表时间:2007-06-30  
gigix 写道
呵呵,另一个有趣的是
@name = ""
attr_writer :name
def set_name(input_name)
  name = input_name 
end

调用set_name不会对@name设值,因为Ruby认为set_name里的name是一个局部变量……

name和@name本来就不一样
0 请登录后投票
   发表时间:2007-06-30  

Jamsa 写道:
最近在学习Rails时把先前在Java中的一些习惯性思维带了过了,结果在遇到self.与@时被这种思维方式给误导了。

遇到这个问题是在使用AcriveRecord时,在修改或者新增记录时需要添加时间戳。首先使用self.posted_at=Time.now来修改字段,一切正常。后来想到在哪篇文章中好像说过self.与Java中的this差不多,这样就不自觉的把posted_at当作了实例变量处理,试了一下用@posted_at=Time.now,没有出错,但是记录的时间并没有被更新。

起初想到书上说ActiveRecord在第一次访问那个类时,将根据表结构信息,自动添加列到实例变量并增加对这些变量的访问器。似乎没有错呀,既然是实例变量不就是@吗?

用instance_values查看才恍然大悟,@attributes这个实例变量保存了各个字段的值。ActiveRecord在初始化这一个类时,添加的实例变量并不是一个数据库字段对应于一个实例变量,而是放到了@atributes里。然后添加了对各个字段的访问器。通过methods方法可以查看实例中的所有方法,可以看到有posted和posted=这两个访问器方法。

self.!=this
self.是方法调用,而不是直接访问实例变量。

从这个错误中,我也清楚了下面三种写法的区别:
1. self.id=        调用id方法。
2. @id=            直接访问实例变量
3. id=                如果前面不加self.,解释器将认为你要给一个局部变量赋值,而不会认为你是要调用id=这个方法修字段id的数据。


只是不同语言的语法不一样罢了,和思维方式没什么关系
0 请登录后投票
   发表时间:2007-06-30  
hideto 写道
gigix 写道
呵呵,另一个有趣的是
@name = ""
attr_writer :name
def set_name(input_name)
  name = input_name 
end

调用set_name不会对@name设值,因为Ruby认为set_name里的name是一个局部变量……

name和@name本来就不一样

attr_writer :name
这句会创建name=方法的
0 请登录后投票
   发表时间:2007-06-30  
set_name方法对name作修改,而不是对@name做修改,当然结果是@name不变

所以说,不同语言不同语法而已
0 请登录后投票
   发表时间:2007-06-30  
在set_name里面调用name=,不会调用obj.name=,而是把name当作local变量,我理解你的意思了gigix,笨啊
0 请登录后投票
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics