You should explicitly use @foo
in the original, aliased setter
; which will add just one line to your code.
- Notice that, as you made
A
superclass, generally you would
want to validate before setting some variables, such as @bar
. This the reason why the validation function was added to the code below (just to reflect this idea).
Also, as attr
s declarations will be translated to methods
, methods are the ones that master the final behaviour and, therefore, in general, it is better to use alias_method
over alias (please, see this widely accepted answer).
I would dare say this is the simplest way to go:
module Aside
class A
attr_reader :bar
# as mentioned, preferable to use alias_method
alias_method :foo, :bar
alias_method :foo=, :bar=
def initialize
# use setter method to keep @bar and @foo in sync
self.bar = 'hello'
end
def bar=(value)
@bar = nil
@bar = value if some_validation?(value)
@foo = @bar
end
private
def some_validation?(value)
value.is_a?(String)
end
end
class B < A
def try_alias
puts @foo
end
end
end
Aside::B.new.try_alias #=> "hello"
Please, observe that the initialize
of the class A
, uses the setter method
, rather than the direct assignment (as in your example), to initialize @bar
.
This is because after aliasing this way, to keep in sync @bar
and @foo
, you should avoid direct variable assignment everywhere other than the bar setter
itself (aside note: that is good practice anyway, because you centralize all the validation of @foo
to one single point).
In other words, when you want to use this approach:
- do not use
direct assignment
: @bar = value
or @foo = value
, and
- use
setter methods
instead : self.bar = value
or self.foo = value
(as shown in the class A
initializer).