Reputation: 59378
Let's say I have a class with a few "static" variables. I want to a subclass of that class to be able to override those variables without affecting the original class. This isn't possible using class variables, since those appears to be shared between subclasses and superclasses:
class Foo
@@test = "a"
def speak; puts @@test; end
end
class Bar < Foo
@@test = "b"
end
Bar.new.speak
# b
Foo.new.speak
# b
It isn't possible using constants either:
class Foo
TEST = "a"
def speak; puts TEST; end
end
class Bar < Foo
TEST = "b"
end
Bar.new.speak
# a
Foo.new.speak
# a
Methods defined in the superclass ignores constants in the subclass.
The obvious workaround is to define methods for the variables that needs to be "overridable":
class Foo
def test; "a"; end
end
But that feels like a hack. I feel like this should be possible using class variables and that I'm probably just doing it wrong. For example, when I subclass Object
(which is what happens by default):
class Foo < Object
@@bar = 123
end
Object.class_variable_get(:@@bar)
# NameError: uninitialized class variable @@bar in Object
Why isn't @@bar
set on Object
like it was in my Bar < Foo
example above?
To summarize: how do I override a variable in a subclass without affecting the superclass?
Upvotes: 8
Views: 8717
Reputation: 3656
Class constants does what you want, you just need to use them differently:
class Foo
TEST = "a"
def speak
puts self.class::TEST
end
end
class Bar < Foo
TEST = "b"
end
Bar.new.speak # => a
Foo.new.speak # => b
Upvotes: 8
Reputation: 78561
Add a variable to the class itself (as in the class instance, rather than a class variable):
class Foo
@var = 'A'
class << self
attr_reader :var
end
def var
self.class.var
end
end
class Bar < Foo
@var = 'B'
end
Foo.var # A
Foo.new.var # A
Bar.var # B
Bar.new.var # B
Upvotes: 4
Reputation: 230521
The correct way (IMHO) is to use methods, because this way you're using inheritance and virtual dispatching, just as you want to.
Class variables are shared down the hierarchy, not up. That's why @@bar
is not available in Object
.
Upvotes: 3