打印

[问题求助] 类中变量的问题

类中变量的问题

大家好,我是一名Java程序员,刚刚开始接触php?name=Ruby" onclick="tagshow(event)" class="t_tag">Ruby,在学习变量的时候碰到这样一个问题,比如有一个类:
class Test
  #@count=0 --- undefined method "+" for nil:NilClass
  def initialize
   @count = 0
  end

  def index

TOP

晕,没贴完整,完整的问题如下:

大家好,我是一名Java程序员,刚刚开始接触Ruby,在学习变量的时候碰到这样一个问题,比如有一个类:

class Test
    #@count=0 --- undefined method "+" for nil:NilClass
    def initialize
        @count = 0
    end

    def index
        @count += 1
    end
end    


问题是,为什么count变量一定要在initialize中定义,而不能简单的在方法外直接定义一个count变量?如果没有initialize方法,直接在方法外面定义变量的话,使用变量的地方似乎认为这个变量未被初始化。看了一些资料,貌似都没有提到这种情况,难道是Ruby不允许在方法外直接执行表达式,至少是不允许定义变量吗?

[ 本帖最后由 sparks 于 2008-3-14 09:11 编辑 ]

TOP



class Test
  attr_accessor :count #其实可能相关的 attr   attr_reader   attr_writer  




test = Test.new
test.count=1


至于这个错误
引用:
undefined method "+" for nil:NilClass
是因为在NilClass上无法操作+,没有这个方法,在这个例子中,你可以简单的用to_i 将他转换为int,不论是否是nil都可以执行的

test.count.to_i+=1


你也可以测试下


一样返回0


如果你觉得麻烦,你可以在NilClass添加相应的操作,这样就不需要你显示的转换了。期待你自己的研究。然后将你的心得写出来,跟和你一样困惑的朋友分享。

TOP

TOP

ruby中的实例变量虽然不用事先定义,就可以拿来直接使用,且默认初始化值是nil,但是并不表示就可以直接放在class的方法之外定义,对与java而言,在class中定义定义一个成员变量不是也要先声明它是一个变量对么?比如java中的

int foobar = 1;


对于ruby来说,在class的方法之外的代码,属于first place code,意味着写在这里的代码,当类加载器载入这个ruby class的事后,就会被执行且只执行一次,这里的代码在跟class load交互,指示class load需要作什么事情~~~
比如一个ruby class文件

class FooBar
  puts 'catch me in first place'
  def foobar
    'catch me in method'
  end
end


然后你在irb中require这个文件,你会发现,require过程中,"puts 'catch me in first place'"这行代码会被执行,然后无论你怎么实例化这个class,这行代码都跟这个class无关了.

TOP

非常感谢大侠的解释,感觉清楚一些了,这个过程好像有些类似Java中的static block,但是不同的是Ruby执行完这些代码后,不管执行了什么,哪怕是定义了变量的值,这些值在class load后也不复存在了,不对这个类available了,这样解释对吗?

另外,如果我在几个类中都require这个类,这部分代码会被执行几次?只是在第一次require的时候被执行,还是每次都执行?也就是说是不是Ruby是不是在每次遇到require的时候都要重新加载这个类?
Ruby oN My Way!

TOP




只会加载一次

irb(main):001:0> require 'fileutils'
=> true
irb(main):002:0> require 'fileutils'
=> false


如你见到的,第二次不会再次加载了。

TOP

可以进一步观察这个"require"方法,他是Kernel的一个方法
http://corelib.rubyonrails.org/classes/Kernel.html#M002060
而Kernal在ruby执行环境中被混入到Object中,所以每次执行require这个方法,其实是在跟ruby的执行环境以及全局类加载器打交道
还用Martin的例子

> require 'fileutils'
=> true


这个时候检查一下全局类加载路径:


你会发现$"这个全局变量(Array类型)的最后一个元素就是你刚刚载入的外部依赖库
当第二次require,Kernel#require方法会先检查这个全局变量$",如果已经加载了,那么当然就不会在一次加载了
(不过Kernel#load方法提供了一个可以重新加载外部依赖库的能力)
这个$"跟整个ruby环境共生共灭,只要在同一个ruby应用实例中,就不需要再次加载

如果我的理解有什么不对的地方,请及时指出~~

[ 本帖最后由 lgn21st 于 2008-3-17 12:01 编辑 ]

TOP

多谢各位的解答,非常透彻了,我是初学Ruby,以后还会有很多问题 ;D
Ruby oN My Way!

TOP

2008-11-24 00:04 Crawled by CCBot/1.0 (+http://www.commoncrawl.org/bot.html) @38.103.63.61