有没有办法引入一些具有以下三个属性的变量/常量?
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))
如果不能简单地通过赋值和引用变量/常量来完成,那么有没有办法实现具有此属性的访问器方法?
您需要使用所需的特定属性创建自己的访问器类型。例如
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
按照约书亚纳波利的建议,我决定这样做:
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