新手问题 Ruby 常量可以赋值???

xautjzd · 2013年05月28日 · 最后由 serco 回复于 2013年05月29日 · 5070 次阅读

今天尝试了下对常量赋值,发现也没有报错,只是给出了警告。难道可以对常量进行赋值么???

可以 Ruby 常量不是 C 常量 凡是内存里的数据 没有不可赋值的 Ruby 已经给出了警告(我记得好像有个什么选项可以彻底阻止的,不过我也没用过 不记得了)但是如果用的是 const_set 那就没有警告了

#1 楼 @iBachue 依然有警告,依然可以修改,我刚尝试过

Ruby 里的常量可以被更改,这点的确跟常见的常量定义不同,这个只要注意下就好了。

#3 楼 @edgar_wang_cn 恩,谢谢回答。细节东西还是得尝试才能记忆深刻,看书本一般容易忽略,而且也不一定会讲到

#1 楼 @iBachue 你好,我刚才尝试用 attr_accessor 来创建类变量的 getter 和 setter 方法,但是报语法错误。attr_accessor:@@varible 这样不行,必须手动写 getter 和 setter 么?还是有其他的方式

#5 楼 @xautjzd

[jasl@Jasl-rMBP:~/workspace/ruby]$ pry
[1] pry(main)> class A
[1] pry(main)*   class<< self
[1] pry(main)*     attr_accessor :foo
[1] pry(main)*   end
[1] pry(main)* end
=> nil
[2] pry(main)> A.foo
=> nil
[3] pry(main)> A.foo = "bar"
=> "bar"
[4] pry(main)> A.foo
=> "bar"
7 楼 已删除

#6 楼 @jasl 这样我试过:

class Test
   class << self
      attr_accessor :count
   end
   def add
      @@count += 1
       puts @@count
    end
end
test = Test.new
Test.count =5
puts Test.count
test.add

这样定义了之后在实例方法中操作类变量就出错。

#2 楼 @xautjzd

#1 楼 @iBachue 依然有警告,依然可以修改,我刚尝试过

哦 那就是要先 remove 掉

#8 楼 @xautjzd 你混淆了 Ruby 的类实例变量和类变量 你在代码中声明了类实例变量却去用类变量 这样的结果是变量找不到。 正确的写法应该是:

class Test
   class << self
      attr_accessor :count
   end

   def add
     self.class.count += 1
     puts self.class.count
   end
end

test = Test.new
Test.count =5
puts Test.count
test.add

#8 楼 @xautjzd 或者用 cattr 操控@@count 类变量

require 'active_support/all'

class Test
   cattr_accessor :count

   def add
      @@count += 1
       puts @@count
    end
end
test = Test.new
Test.count =5
puts Test.count
test.add

#11 楼 @iBachue 谢谢了,真的是有点懵了,没搞清类变量、类实例变量和实例变量之间的差异。

#12 楼 @xautjzd 你熟悉别的语言么。我觉得学会用@,基本上就可以了。

#13 楼 @chenge java 吧,实例变量与类实例变量不是一个概念?

#14 楼 @xautjzd 这个中文翻译没有统一,最好是就代码来说。@就是实例变量吧。另外还有@@,这个不推荐使用。

#15 楼 @chenge 那就懂了,@是类的实例所有,而@@是所有实例共有

#15 楼 @chenge

class Test
   class << self
      attr_accessor :count
   end
   def add
      @count += 1
       puts @count
    end
end
test = Test.new
Test.count =5
puts Test.count
test.add

count 定义为实例变量,但是 add 中也访问不了

#17 楼 @xautjzd


class Test
   attr_writer :count
   def initialize 
    @count = 2
  end
   def add
      @count += 1
       puts @count
    end
end
test = Test.new
test.count =5
#puts Test.count
test.add

#18 楼 @chenge 这个我当然明白,现在是要将 attr_accessor :count 在类方法中定义。然后实例方法来访问

#19 楼 @xautjzd 前面 10 楼不是写了么?感觉没必要纠缠这个啊。

#20 楼 @chenge #19 楼 @xautjzd 我觉得你是没理解 class << self 的意思。。

#20 楼 @chenge 有问题肯定要弄懂,现在 10 楼是通过 count 的 getter 和 setter 方法来操作的,既然是实例变量,就该可以在 add 实例方法内部操作这个实例变量,而不需要再借助 getter 和 setter 了

#10 楼 @iBachue 你好,你在 add 中操作实例变量 count 时是借助 getter 和 setter 的,self.class.count += 1,我想着直接对变量操作

#21 楼 @serco 这不是声明类方法么?还有一本书写的是元类

#23 楼 @xautjzd 那就更繁琐了

class Test
   class << self
      attr_accessor :count
   end

   def add
     self.class.class_exec do
       @count += 1
       puts @count
     end
   end
end

test = Test.new
Test.count =5
puts Test.count
test.add

#16 楼 @xautjzd

那就懂了,@是类的实例所有,而@@是所有实例共有

后面半句不完全对

#23 楼 @xautjzd

class Test
    class << self
        attr_accessor :count
    end
end

这个 count 是 Test 的 Class_Instance_Variable,而你在 17 楼写的 add 方法是 Test 的实例的方法,test 是 Test 的实例,count 是 Class_Instance 的变量,你怎么可能在一个实例中直接操作另一个实例的变量而不用 setter,getter 呢?

#27 楼 @serco Class_Instance 不就是类的实例变量么?类的实例方法不能操作实例变量么

#26 楼 @iBachue @@不是类的所有实例所共享的么?我说的是@@属于类,所有对象共享这个类变量。

#29 楼 @xautjzd 不对呀 你这个是 Java/C++ 的类变量。在 Ruby 中,类实例变量才是类所有的,而类变量则比较奇葩,它隶属于整个类的继承体系,而不属于任何一个类所有。

#28 楼 @xautjzd 这里所说的 Class_Instance 并非平时常见的实例。 Ruby 中 每一个类本身也是 Class 的 实例。 所以上述中的 Test 是 Class 类的一个实例,上述创建的 count 变量实际是 Test 这个 Class 实例自身的变量,地位等同@@count(只是@@count 能被继承和 Test 的真正实例直接访问)。而你的 add 方法的 self 指向的是 Test 的真正实例,如你写的 test。add 能直接操作的只是 Test 的实例变量,而不能直接操作上述中的 count。

Ruby 有所谓域门,在 class 关键字直接范围下,self 指代 class 自身,而一旦进入 def 关键字下,那 self 就指代之后会创建的实例对象了。

class Test
    @var1  #这个是Class类的实例Test的变量

    def some_func
        @var2  #这个是Test.new创建的实例的变量
    end

end

指代不同,当然不能直接操作了。我不一定能表述得清楚,具体可以去看《Ruby 元编程》。Good luck.

Ruby 常量可以赋值,松本的编程世界里面特意强调了这一点

实例变量属于实例所有,类变量属于类所有,有什么问题?类不也是对象么,如果真要深究,还是看 Ruby 源码比较好

#33 楼 @SharpX 我觉得他可能只是从别的语言转过来被惊讶到了

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