修改子类的常量

时间:2013-03-04 00:16:12

标签: ruby

我是Ruby的新手,请原谅可能的noob问题,但到目前为止谷歌一直没有帮助。

我在父类

中定义了一个类常量
Items = [[1, 3, 5], [2, 4, 6]]

然后我有一个子类,我想在Items数组中添加一个数组[1,5,9]。你能以这种方式引用超级/重新定义常量吗?

这样的东西
Items = super.Items.concat([1, 5, 9])

我不想将Items定义复制到我的子类中,附加项目。

3 个答案:

答案 0 :(得分:5)

常量是在定义它们的类或模块中的名称间隔。他们通过通常的祖先路径解决。在您的子类中,您可以定义与超类中的名称相同的常量,并且初始化它的表达式可以引用超类的常量,因为在初始赋值之后才会定义子类的常量。像这样:

$ pry
[1] pry(main)> class A; Items = [[1, 3, 5], [2, 4, 6]]; end
=> [[1, 3, 5], [2, 4, 6]]
[2] pry(main)> class B < A; end
=> nil
[3] pry(main)> class B; Items; end
=> [[1, 3, 5], [2, 4, 6]]
[4] pry(main)> A::Items
=> [[1, 3, 5], [2, 4, 6]]
[5] pry(main)> B::Items
=> [[1, 3, 5], [2, 4, 6]]
[6] pry(main)> class B; Items = Items.dup << [7,8,9]; end
=> [[1, 3, 5], [2, 4, 6], [7, 8, 9]]
[7] pry(main)> A::Items
=> [[1, 3, 5], [2, 4, 6]]
[8] pry(main)> B::Items
=> [[1, 3, 5], [2, 4, 6], [7, 8, 9]]

在推导新常量时,如果您计划使用变异方法(如Array#<<)修改原始常量,请小心dup原始常量。看到陷阱:

[9] pry(main)> class A; Foo = [[1,2],[3,4]]; end
=> [[1, 2], [3, 4]]
[10] pry(main)> A::Foo
=> [[1, 2], [3, 4]]
[11] pry(main)> class B; Foo = Foo << [5,6]; end
=> [[1, 2], [3, 4], [5, 6]]
[12] pry(main)> B::Foo
=> [[1, 2], [3, 4], [5, 6]]
[13] pry(main)> A::Foo
=> [[1, 2], [3, 4], [5, 6]]
[14] pry(main)> B::Foo.object_id == A::Foo.object_id
=> true
[15] pry(main)> B::Items.object_id == A::Items.object_id
=> false

您可以在父命名空间中显式引用常量,而无需使用Class#superclass

命名超类
[16] pry(main)> class B; superclass::Items; end
=> [[1, 3, 5], [2, 4, 6]]

答案 1 :(得分:2)

在Ruby中,常量查找并不总是非常明显,特别是因为它通常不是作用域的(例如我们写String,而不是::String

您可以在子类中覆盖它。您可以通过访问superclass

来构建它
class C < Base
  CONST = build_on(superclass::CONST)
end

你必须要小心如何从实例和单例方法访问常量:

class Base
  FOO = [42]

  def self.naive
    FOO
  end

  def naive_ins
    FOO
  end

  def self.aware
    self::FOO
  end

  def aware_ins
    self.class::FOO
  end
end

class C < Base
  FOO = superclass::FOO + [:bar]
end

C.naive # => [42]
C.new.naive_ins # => [42]
C.aware # => [42, :bar]
C.new.aware_ins # => [42, :bar]

答案 2 :(得分:0)

常量的作用域是定义它们的类。因此,如果需要,可以在子类中重新定义常量。