假设我想在Ruby中创建一个宏。
class Base
def self.option(name,val)
options[name] = val
end
def self.options
@options ||= {}
end
end
class Foo < Base
option :one, 1
option :two, 2
end
Foo.options #=> {:one => 1, :two => 2}
好的,很容易。
但是如果我想继承Foo怎么办?
class Bar < Foo
end
Bar.options #=> {}
太糟糕了。
所以很清楚问题是类实例变量是每个类唯一的,即。 @options
内的Bar
与@options
内的Foo
不同。
那么也许是一个类变量?我从来没有能够找到其中一个的有效用途,让我们尝试一下。
# the rest of the code unchanged
class Base
def self.options
@@options ||= {}
end
end
Bar.options #=> {:one => 1, :two => 2}
嘿,那有效! ......不是吗?
class Baz < Foo
option :three, 3
end
Foo.options #=> {:one => 1, :two => 2, :three => 3}
Bar.options #=> {:one => 1, :two => 2, :three => 3}
Baz.options #=> {:one => 1, :two => 2, :three => 3}
X- |
好的,我一直在谷歌搜索这个,我没有看到任何有用的东西。我尝试了一些尝试阅读超类选项(如果已定义)但却无处可寻。我想我也可以问。
你们任何人都知道怎么做?或者它是不可能的......
答案 0 :(得分:1)
我相信这就是你所需要的:
class Base
def self.option(name, val)
options[name] = val
end
def self.options
@options ||= if self.superclass.respond_to?(:options)
self.superclass.options.dup
else
{}
end
end
end
class Foo < Base
option :one, 1
option :two, 2
end
class Bar < Foo
option :three, 3
end
class Hello < Bar
option :world, 4
end
puts Foo.options # {:one=>1, :two=>2}
puts Bar.options # {:one=>1, :two=>2, :three=>3}
puts Hello.options #{:one=>1, :two=>2, :three=>3, :world=>4}
答案 1 :(得分:1)
如果你想要一个足够通用的东西,以便在从它派生子类之后适应基类中所做的更改:
class Base
def self.option(name,val)
@options ||= { }
@options[name] = val
end
def self.options
@options ||= { }
if (self == Base)
@options
else
@options.merge(self.superclass.options)
end
end
end
class Foo < Base
option :one, 1
option :two, 2
end
class SubFoo < Foo
option :three, 3
end
Foo.options
#=> {:one => 1, :two => 2}
SubFoo.options
#=> {:three=>3, :one=>1, :two=>2}
class Foo
option :four, 4
end
Foo.options
#=> {:one=>1, :two=>2, :four=>4}
SubFoo.options
#=> {:three=>3, :one=>1, :two=>2, :four=>4}
答案 2 :(得分:0)
class Base
def self.option(name,val)
options[name] = val
end
def self.options
@options ||= {}
end
end
class Foo < Base
option :one, 1
option :two, 2
end
class Bar < Foo
@options = superclass.options.clone
option :three, 3
end
class Baz < Foo
@options = superclass.options.clone
option :four, 4
end
puts Foo.options #=> {:one => 1, :two => 2}
puts Bar.options #=> {:one => 1, :two => 2, :three => 3}
puts Baz.options #=> {:one => 1, :two => 2, :four => 4}
这是我能想到的唯一可行的方法,你只需从超类中克隆@options
。这样,每个类都有自己独立的实例变量。