【问题标题】:A variable/constant that inherits but does not share with the superclass, and does not share namespace继承但不与超类共享且不共享命名空间的变量/常量
【发布时间】:2013-01-27 00:59:55
【问题描述】:

有没有办法通过以下三个属性引入一些变量/常数?

a) 当它没有在自己的类中分配时,它会继承超类的值。

b) 它不继承超类以外的其他类的值(即使它们共享命名空间)。

c) 在自己的类中赋值时不会覆盖超类的值。

使用类实例变量,a) 不满足。

class A; @foo = :foo end
class B < A; @foo end # => nil  (Does not satisfy (a))
class A; class C; @foo end end # => nil (Satisfies (b))

class B < A; @foo = :bar end
class A; @foo end # => :foo  (Satisfies (c))

使用类变量,c) 不满足。

class A; @@foo = :foo end
class B < A; @@foo end # => :foo  (Satisfies (a))
class A; class C; @foo end end # => NameError (Satisfies (b))

class B < A; @@foo = :bar end
class A; @foo end # => :bar  (Does not satisfy (c))

使用常数,b) 不满足。

class A; Foo = :foo end
class B < A; Foo end # => :foo  (Satisfies (a))
class A; class C; Foo end end # => :foo (Does not satisfy (b))

class B < A; Foo = :bar end
class A; Foo end # => :foo  (Satisfies (c))

我想要这样的东西:

class A; something = :foo end
class B < A; something end # => :foo  (Satisfies (a))
class A; class C; something end end # => nil or Error (Satisfies (b))

class B < A; something = :bar end
class A; something end # => :foo  (Satisfies (c))

如果不能简单地通过分配和引用变量/常量来完成,那么有没有办法实现具有此属性的访问器方法?

【问题讨论】:

    标签: ruby variables constants


    【解决方案1】:

    您需要使用所需的特定属性创建自己的访问器类型。例如,

    module InheritableProperty
      def property
        @property || superclass.property
      end
      def property=(value)
        @property = value
      end
    end
    
    class A
      extend InheritableProperty
    end
    class B < A
      extend InheritableProperty
      class C
        extend InheritableProperty
      end
    end
    
    A.property = 1
    A.property # => 1
    B.property # => 1
    B::C.property # error
    
    A.property = 1
    B.property = 2
    A.property # => 1
    B.property # => 2
    B::C.property # error
    
    A.property = 1
    B.property = 2
    B::C.property = 3
    A.property # => 1
    B.property # => 2
    B::C.property # => 3
    

    【讨论】:

      【解决方案2】:

      按照 joshuanapoli 的建议,我决定这样做:

      class A
        def self.foo; defined?(@foo) ? @foo : superclass.foo end
      end
      
      class A; @foo = :foo end
      class B < A; foo end # => :foo
      class A; class C; foo end end # => Error
      class B < A; @foo = :bar end
      class A; foo end # => :foo
      

      【讨论】:

        猜你喜欢
        • 2012-05-19
        • 1970-01-01
        • 2020-10-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多