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?
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
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With